Changes to make use of code taken from libassuan. This replaces the
[gnupg.git] / g10 / g10.c
index 313c007..fefb8ab 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,6 +1,6 @@
 /* g10.c - The GnuPG utility (main for gpg)
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- *               2004 Free Software Foundation, Inc.
+ *               2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -33,6 +33,7 @@
 #ifdef HAVE_STAT
 #include <sys/stat.h> /* for stat() */
 #endif
+#include <fcntl.h>
 
 #define INCLUDED_BY_MAIN_MODULE 1
 #include "packet.h"
 #include "keyserver-internal.h"
 #include "exec.h"
 #include "cardglue.h"
+#ifdef ENABLE_CARD_SUPPORT
+#include "ccid-driver.h"
+#endif
+
+#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
   {
@@ -75,6 +90,7 @@ enum cmd_and_opt_values
     oVerbose     = 'v',
     oCompress    = 'z',
     oSetNotation  = 'N',
+    aListSecretKeys = 'K',
     oBatch       = 500,
     oMaxOutput,
     oSigNotation,
@@ -92,8 +108,6 @@ enum cmd_and_opt_values
     aSignSym,
     aSignKey,
     aLSignKey,
-    aNRSignKey,
-    aNRLSignKey,
     aListConfig,
     aGPGConfList,
     aListPackets,
@@ -109,7 +123,6 @@ enum cmd_and_opt_values
     aVerifyFiles,
     aListKeys,
     aListSigs,
-    aListSecretKeys,
     aSendKeys,
     aRecvKeys,
     aSearchKeys,
@@ -167,14 +180,11 @@ enum cmd_and_opt_values
     oOptions,
     oDebug,
     oDebugAll,
+    oDebugCCIDDriver,
     oStatusFD,
-#ifdef __riscos__
     oStatusFile,
-#endif /* __riscos__ */
     oAttributeFD,
-#ifdef __riscos__
     oAttributeFile,
-#endif /* __riscos__ */
     oSKComments,
     oNoSKComments,
     oEmitVersion,
@@ -191,6 +201,8 @@ enum cmd_and_opt_values
     oPGP6,
     oPGP7,
     oPGP8,
+    oRFC2440Text,
+    oNoRFC2440Text,
     oCipherAlgo,
     oDigestAlgo,
     oCertDigestAlgo,
@@ -199,17 +211,15 @@ enum cmd_and_opt_values
     oBZ2CompressLevel,
     oBZ2DecompressLowmem,
     oPasswdFD,
-#ifdef __riscos__
     oPasswdFile,
-#endif /* __riscos__ */
     oCommandFD,
-#ifdef __riscos__
     oCommandFile,
-#endif /* __riscos__ */
     oQuickRandom,
     oNoVerbose,
     oTrustDBName,
     oNoSecmemWarn,
+    oRequireSecmem,
+    oNoRequireSecmem,
     oNoPermissionWarn,
     oNoMDCWarn,
     oNoArmor,
@@ -242,8 +252,8 @@ enum cmd_and_opt_values
     oComment,
     oDefaultComment,
     oNoComments,
-    oThrowKeyid,
-    oNoThrowKeyid,
+    oThrowKeyids,
+    oNoThrowKeyids,
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
@@ -278,9 +288,7 @@ enum cmd_and_opt_values
     oHiddenEncryptTo,
     oNoEncryptTo,
     oLoggerFD,
-#ifdef __riscos__
     oLoggerFile,
-#endif /* __riscos__ */
     oUtf8Strings,
     oNoUtf8Strings,
     oDisableCipherAlgo,
@@ -342,8 +350,6 @@ enum cmd_and_opt_values
     octapiDriver,
     opcscDriver,
     oDisableCCID,
-    oAllowAdmin,
-    oDenyAdmin,
 
     aTest
   };
@@ -376,8 +382,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, "@" },
@@ -483,13 +487,9 @@ static ARGPARSE_OPTS opts[] = {
     { oDebug, "debug"     ,4|16, "@"},
     { oDebugAll, "debug-all" ,0, "@"},
     { oStatusFD, "status-fd" ,1, "@"},
-#ifdef __riscos__
     { oStatusFile, "status-file" ,2, "@"},
-#endif /* __riscos__ */
     { oAttributeFD, "attribute-fd" ,1, "@" },
-#ifdef __riscos__
     { oAttributeFile, "attribute-file" ,2, "@" },
-#endif /* __riscos__ */
     { oNoSKComments, "no-sk-comments", 0,   "@"},
     { oSKComments, "sk-comments", 0,   "@"},
     { oCompletesNeeded, "completes-needed", 1, "@"},
@@ -509,6 +509,8 @@ static ARGPARSE_OPTS opts[] = {
     { oPGP6, "pgp6", 0, "@"},
     { oPGP7, "pgp7", 0, "@"},
     { oPGP8, "pgp8", 0, "@"},
+    { oRFC2440Text, "rfc2440-text", 0, "@"},
+    { oNoRFC2440Text, "no-rfc2440-text", 0, "@"},
     { oS2KMode, "s2k-mode", 1, "@"},
     { oS2KDigest, "s2k-digest-algo", 2, "@"},
     { oS2KCipher, "s2k-cipher-algo", 2, "@"},
@@ -517,8 +519,11 @@ static ARGPARSE_OPTS opts[] = {
     { oDigestAlgo, "digest-algo", 2, "@"},
     { oCertDigestAlgo, "cert-digest-algo", 2 , "@" },
     { oCompressAlgo,"compress-algo", 2, "@"},
-    { oThrowKeyid, "throw-keyids", 0, "@"},
-    { oNoThrowKeyid, "no-throw-keyids", 0, "@" },
+    { 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, "@" },
@@ -526,10 +531,6 @@ static ARGPARSE_OPTS opts[] = {
     { oSetNotation,  "notation-data", 2, "@" }, /* Alias */
     { oSigNotation,  "sig-notation", 2, "@" },
     { oCertNotation, "cert-notation", 2, "@" },
-#ifdef ENABLE_CARD_SUPPORT
-    { oAllowAdmin, "allow-admin",0,N_("allow the use of admin card commands")},
-    { oDenyAdmin,  "deny-admin",0,"@"},
-#endif
 
     { 302, NULL, 0, N_(
   "@\n(See the man page for a complete listing of all commands and options)\n"
@@ -544,7 +545,6 @@ 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 */
@@ -552,17 +552,15 @@ static ARGPARSE_OPTS opts[] = {
     { aPipeMode,  "pipemode", 0, "@" },
     { oKOption, NULL,   0, "@"},
     { oPasswdFD, "passphrase-fd",1, "@" },
-#ifdef __riscos__
     { oPasswdFile, "passphrase-file",2, "@" },
-#endif /* __riscos__ */
     { oCommandFD, "command-fd",1, "@" },
-#ifdef __riscos__
     { oCommandFile, "command-file",2, "@" },
-#endif /* __riscos__ */
     { oQuickRandom, "quick-random", 0, "@"},
     { oNoVerbose, "no-verbose", 0, "@"},
     { oTrustDBName, "trustdb-name", 2, "@" },
-    { oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
+    { 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, "@"},
@@ -611,9 +609,7 @@ static ARGPARSE_OPTS opts[] = {
     { oLockMultiple, "lock-multiple", 0, "@" },
     { oLockNever, "lock-never", 0, "@" },
     { oLoggerFD, "logger-fd",1, "@" },
-#ifdef __riscos__
     { oLoggerFile, "logger-file",2, "@" },
-#endif /* __riscos__ */
     { oUseEmbeddedFilename, "use-embedded-filename", 0, "@" },
     { oNoUseEmbeddedFilename, "no-use-embedded-filename", 0, "@" },
     { oUtf8Strings, "utf8-strings", 0, "@" },
@@ -681,10 +677,21 @@ static ARGPARSE_OPTS opts[] = {
     { octapiDriver, "ctapi-driver",  2, "@"},
     { opcscDriver, "pcsc-driver",    2, "@"},
     { oDisableCCID, "disable-ccid", 0, "@"},
+#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
+    { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"},
+#endif
 
     {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;
 
 static int utf8_strings = 0;
@@ -832,7 +839,7 @@ static void
 i18n_init(void)
 {
 #ifdef USE_SIMPLE_GETTEXT
-    set_gettext_file( PACKAGE );
+    set_gettext_file (PACKAGE, "Software\\GNU\\GnuPG");
 #else
 #ifdef ENABLE_NLS
     setlocale( LC_ALL, "" );
@@ -917,6 +924,51 @@ set_screen_dimensions(void)
 }
 
 
+/* 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 )
 {
@@ -966,7 +1018,7 @@ add_group(char *string)
   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;
     }
 
@@ -1163,50 +1215,50 @@ 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);
        }
     }
 
@@ -1327,11 +1379,26 @@ list_config(char *items)
          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);
+       log_error(_("unknown configuration item `%s'\n"),name);
     }
 }
 
@@ -1353,9 +1420,120 @@ gpgconf_list (const char *configfile)
   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;
+       }
+    }
+
+  m_free(opt.show_subpackets);
+  opt.show_subpackets=m_alloc(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},
+      {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL},
+      {"show-notations",LIST_SHOW_NOTATIONS,NULL},
+      {"show-std-notations",LIST_SHOW_STD_NOTATIONS,NULL},
+      {"show-standard-notations",LIST_SHOW_STD_NOTATIONS,NULL},
+      {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL},
+      {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL},
+      {"show-uid-validity",LIST_SHOW_UID_VALIDITY,NULL},
+      {"show-unusable-uids",LIST_SHOW_UNUSABLE_UIDS,NULL},
+      {"show-unusable-subkeys",LIST_SHOW_UNUSABLE_SUBKEYS,NULL},
+      {"show-keyring",LIST_SHOW_KEYRING,NULL},
+      {"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL},
+      {"show-sig-subpackets",LIST_SHOW_SIG_SUBPACKETS,NULL},
+      {NULL,0,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' */
+         m_free(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 *
@@ -1382,6 +1560,22 @@ collapse_args(int argc,char *argv[])
   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 )
@@ -1424,6 +1618,7 @@ 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 USE_SHM_COPROCESSING
     ulong requested_shm_size=0;
 #endif
@@ -1453,7 +1648,6 @@ main( int argc, char **argv )
     opt.cert_digest_algo = 0;
     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
@@ -1466,9 +1660,9 @@ main( int argc, char **argv )
     opt.force_v3_sigs = 1;
     opt.escape_from = 1;
     opt.import_options=IMPORT_SK2PK;
-    opt.export_options=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_ATTRIBUTES;
+    opt.keyserver_options.export_options=EXPORT_ATTRIBUTES;
     opt.keyserver_options.options=
       KEYSERVER_INCLUDE_SUBKEYS|KEYSERVER_INCLUDE_REVOKED|KEYSERVER_TRY_DNS_SRV|KEYSERVER_HONOR_KEYSERVER_URL;
     opt.verify_options=
@@ -1478,14 +1672,8 @@ main( int argc, char **argv )
     opt.min_cert_level=2;
     set_screen_dimensions();
     opt.keyid_format=KF_SHORT;
-#if defined (_WIN32)
-    set_homedir ( read_w32_registry_string( NULL,
-                                    "Software\\GNU\\GnuPG", "HomeDir" ));
-#else
-    set_homedir ( getenv("GNUPGHOME") );
-#endif
-    if( !*opt.homedir )
-       set_homedir ( GNUPG_HOMEDIR );
+    opt.rfc2440_text=1;
+    set_homedir ( default_homedir () );
 
 #ifdef ENABLE_CARD_SUPPORT
 # ifdef _WIN32
@@ -1557,10 +1745,17 @@ main( int argc, char **argv )
     }
 #endif
     /* initialize the secure memory. */
-    secmem_init( 32768 );
+    got_secmem=secmem_init( 32768 );
     maybe_setuid = 0;
     /* Okay, we are now working under our real uid */
 
+#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
+
     set_native_charset (NULL); /* Try to auto set the character set */
 
     /* Try for a version specific config file first */
@@ -1631,6 +1826,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 )
@@ -1697,8 +1898,6 @@ 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;
@@ -1733,8 +1932,6 @@ main( int argc, char **argv )
           case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
           case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
           case oDisableCCID: opt.disable_ccid = 1; break;
-          case oAllowAdmin: opt.allow_admin = 1; break;
-          case oDenyAdmin: opt.allow_admin = 0; break;
 #endif /* ENABLE_CARD_SUPPORT*/
 
          case oArmor: opt.armor = 1; opt.no_armor=0; break;
@@ -1777,37 +1974,38 @@ main( int argc, char **argv )
            break;
          case oDebug: opt.debug |= pargs.r.ret_ulong; break;
          case oDebugAll: opt.debug = ~0; break;
+          case oDebugCCIDDriver: 
+#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB)
+            ccid_set_debug_level (1);
+#endif
+            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_logfile( NULL,
-                             iobuf_translate_file_handle (pargs.r.ret_int, 1) );
+                             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) );
+            log_set_logfile( NULL, open_info_file (pargs.r.ret_str, 1) );
             break;
-#endif /* __riscos__ */
+
          case oWithFingerprint:
             opt.with_fingerprint = 1;
             with_fpr=1; /*fall thru*/
          case oFingerprint: opt.fingerprint++; break;
-         case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
+         case oSecretKeyring:
+            append_to_strlist( &sec_nrings, pargs.r.ret_str);
+            break;
          case oOptions:
            /* config files may not be nested (silently ignore them) */
            if( !configfp ) {
@@ -1859,16 +2057,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"),
@@ -1876,7 +2065,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;
@@ -1884,8 +2073,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);
@@ -1899,17 +2088,18 @@ 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;
@@ -1926,6 +2116,8 @@ main( int argc, char **argv )
          case oPGP8:  opt.compliance = CO_PGP8;  break;
          case oGnuPG: opt.compliance = CO_GNUPG; break;
          case oCompressSigs: opt.compress_sigs = 1; break;
+         case oRFC2440Text: opt.rfc2440_text=1; break;
+         case oNoRFC2440Text: opt.rfc2440_text=0; break;
          case oRunAsShmCP:
 #ifndef __riscos__
 # ifndef USE_SHM_COPROCESSING
@@ -1977,8 +2169,8 @@ 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 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");
@@ -2051,21 +2243,21 @@ main( int argc, char **argv )
             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 = m_strdup(pargs.r.ret_str);
+            break;
+         case oDigestAlgo:
+            def_digest_string = m_strdup(pargs.r.ret_str);
             break;
-#endif /* __riscos__ */
-         case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
-         case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
          case oCompressAlgo:
            /* If it is all digits, stick a Z in front of it for
               later.  This is for backwards compatibility with
@@ -2092,12 +2284,14 @@ main( int argc, char **argv )
            break;
          case oCertDigestAlgo: cert_digest_string = m_strdup(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 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;
@@ -2148,33 +2342,14 @@ main( int argc, char **argv )
              }
            break;
          case oListOptions:
-           {
-             struct parse_options lopts[]=
-               {
-                 {"show-photos",LIST_SHOW_PHOTOS,NULL},
-                 {"show-policy-urls",LIST_SHOW_POLICY_URLS,NULL},
-                 {"show-notations",LIST_SHOW_NOTATIONS,NULL},
-                 {"show-std-notations",LIST_SHOW_STD_NOTATIONS,NULL},
-                 {"show-standard-notations",LIST_SHOW_STD_NOTATIONS,NULL},
-                 {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL},
-                 {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL},
-                 {"show-validity",LIST_SHOW_VALIDITY,NULL},
-                 {"show-unusable-uids",LIST_SHOW_UNUSABLE_UIDS,NULL},
-                 {"show-unusable-subkeys",LIST_SHOW_UNUSABLE_SUBKEYS,NULL},
-                 {"show-keyring",LIST_SHOW_KEYRING,NULL},
-                 {"show-sig-expire",LIST_SHOW_SIG_EXPIRE,NULL},
-                 {NULL,0,NULL}
-               };
-
-             if(!parse_options(pargs.r.ret_str,&opt.list_options,lopts,1))
-               {
-                 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:
            {
@@ -2187,7 +2362,7 @@ main( int argc, char **argv )
                  {"show-standard-notations",VERIFY_SHOW_STD_NOTATIONS,NULL},
                  {"show-user-notations",VERIFY_SHOW_USER_NOTATIONS,NULL},
                  {"show-keyserver-urls",VERIFY_SHOW_KEYSERVER_URLS,NULL},
-                 {"show-validity",VERIFY_SHOW_VALIDITY,NULL},
+                 {"show-uid-validity",VERIFY_SHOW_UID_VALIDITY,NULL},
                  {"show-unusable-uids",VERIFY_SHOW_UNUSABLE_UIDS,NULL},
                  {NULL,0,NULL}
                };
@@ -2204,7 +2379,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;
@@ -2337,7 +2512,7 @@ main( int argc, char **argv )
            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);
+             log_error("unknown keyid-format `%s'\n",pargs.r.ret_str);
            break;
 
          default : pargs.err = configfp? 1:2; break;
@@ -2416,6 +2591,14 @@ main( int argc, char **argv )
                        "--no-literal" );
     }
 
+#ifndef ENABLE_AGENT_SUPPORT   
+    if (opt.use_agent) {
+      log_info(_("NOTE: %s is not available in this version\n"),
+               "--use-agent");
+      opt.use_agent = 0;
+    }
+#endif /*!ENABLE_AGENT_SUPPORT*/
+
     if (opt.set_filesize)
        log_info(_("NOTE: %s is not for normal use!\n"), "--set-filesize");
     if( opt.batch )
@@ -2423,6 +2606,13 @@ main( int argc, char **argv )
 
     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
 
+    if(require_secmem && !got_secmem)
+      {
+       log_info(_("will not run with insecure memory due to %s\n"),
+                "--require-secmem");
+       g10_exit(2);
+      }
+
     set_debug();
 
     /* Do these after the switch(), so they can override settings. */
@@ -2493,6 +2683,8 @@ main( int argc, char **argv )
            opt.ask_cert_expire = 0;
            m_free(def_digest_string);
            def_digest_string = m_strdup("md5");
+           m_free(s2k_digest_string);
+           s2k_digest_string = m_strdup("md5");
            opt.compress_algo = COMPRESS_ALGO_ZIP;
          }
       }
@@ -2677,18 +2869,18 @@ main( int argc, char **argv )
            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:
@@ -2703,6 +2895,8 @@ main( int argc, char **argv )
     if( use_random_seed ) {
        char *p = make_filename(opt.homedir, "random_seed", NULL );
        set_random_seed_file(p);
+        if (!access (p, F_OK))
+          register_secured_file (p);
        m_free(p);
     }
 
@@ -2735,20 +2929,26 @@ main( int argc, char **argv )
     /* Add the keyrings, but not for some special commands and not in
        case of "-kvv userid keyring".  Also avoid adding the secret
        keyring for a couple of commands to avoid unneeded access in
-       case the secrings are stored on a floppy */
-    if( cmd != aDeArmor && cmd != aEnArmor
-       && !(cmd == aKMode && argc == 2 ) ) 
+       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 );
       }
@@ -2799,15 +2999,15 @@ main( int argc, char **argv )
        if( argc > 1 )
            wrong_args(_("--store [filename]"));
        if( (rc = encode_store(fname)) )
-           log_error_f( print_fname_stdin(fname),
-                       "store failed: %s\n", g10_errstr(rc) );
+           log_error ("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_f(print_fname_stdin(fname),
-                       "symmetric encryption failed: %s\n",g10_errstr(rc) );
+            log_error (_("symmetric encryption of `%s' failed: %s\n"),
+                        print_fname_stdin(fname),g10_errstr(rc) );
        break;
 
       case aEncr: /* encrypt the given file */
@@ -2953,13 +3153,6 @@ main( int argc, char **argv )
        if( argc != 1 )
          wrong_args(_("--lsign-key user-id"));
        /* fall through */
-      case aNRSignKey:
-       if( argc != 1 )
-         wrong_args(_("--nrsign-key user-id"));
-       /* fall through */
-      case aNRLSignKey:
-       if( argc != 1 )
-         wrong_args(_("--nrlsign-key user-id"));
 
        sl=NULL;
 
@@ -2967,10 +3160,6 @@ main( int argc, char **argv )
          append_to_strlist(&sl,"sign");
        else if(cmd==aLSignKey)
          append_to_strlist(&sl,"lsign");
-       else if(cmd==aNRSignKey)
-         append_to_strlist(&sl,"nrsign");
-       else if(cmd==aNRLSignKey)
-         append_to_strlist(&sl,"nrlsign");
        else
          BUG();
 
@@ -3039,7 +3228,7 @@ main( int argc, char **argv )
        }
        else if( argc == 2 ) { /* -kv userid keyring */
            if( access( argv[1], R_OK ) ) {
-               log_error(_("can't open %s: %s\n"),
+               log_error(_("can't open `%s': %s\n"),
                               print_fname_stdin(argv[1]), strerror(errno));
            }
            else {
@@ -3061,17 +3250,17 @@ main( int argc, char **argv )
        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;
@@ -3355,9 +3544,9 @@ main( int argc, char **argv )
 
       case aChangePIN:
         if (!argc)
-            change_pin (0);
+            change_pin (0,1);
         else if (argc == 1)
-            change_pin ( atoi (*argv));
+            change_pin (atoi (*argv),1);
         else
         wrong_args ("--change-pin [no]");
         break;
@@ -3381,7 +3570,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 {
 
@@ -3554,6 +3750,12 @@ 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) );
@@ -3664,8 +3866,7 @@ add_notation_data( const char *string, int which )
 
     if(!saw_at && !opt.expert)
       {
-       log_error(
-               _("a user notation name must contain the '@' character\n"));
+       log_error(_("a user notation name must contain the '@' character\n"));
        return;
       }
 
@@ -3675,8 +3876,8 @@ add_notation_data( const char *string, int which )
        if ((*s & 0x80))
           highbit = 1;
        else if (iscntrl(*s)) {
-           log_error(_("a notation value must not use "
-                       "any control characters\n") );
+           log_error(_("a notation value must not use"
+                       " any control characters\n") );
            return;
        }
     }
@@ -3744,8 +3945,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)