diff options
Diffstat (limited to '')
-rw-r--r-- | g10/gpg.c | 2196 |
1 files changed, 1446 insertions, 750 deletions
@@ -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 <[email protected]>.\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; } - |