Comment changes.
[gnupg.git] / g10 / misc.c
index 12aa6c6..8cc63ba 100644 (file)
@@ -1,12 +1,12 @@
 /* misc.c - miscellaneous functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005, 2006 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ *               2008, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 
 #include "gpg.h"
 #ifdef HAVE_W32_SYSTEM
-# include "errors.h"
-# include "dynload.h"
+# include "status.h"
 #endif /*HAVE_W32_SYSTEM*/
 #include "util.h"
 #include "main.h"
 #include "photoid.h"
 #include "options.h"
+#include "call-agent.h"
 #include "i18n.h"
 
 
@@ -94,51 +92,6 @@ static struct secured_file_item *secured_files;
 
 
 
-#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
-static int
-setsysinfo(unsigned long op, void *buffer, unsigned long size,
-                    int *start, void *arg, unsigned long flag)
-{
-    return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
-}
-
-void
-trap_unaligned(void)
-{
-    unsigned int buf[2];
-
-    buf[0] = SSIN_UACPROC;
-    buf[1] = UAC_SIGBUS | UAC_NOPRINT;
-    setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
-}
-#else
-void
-trap_unaligned(void)
-{  /* dummy */
-}
-#endif
-
-
-int
-disable_core_dumps()
-{
-#ifdef HAVE_DOSISH_SYSTEM
-    return 0;
-#else
-#ifdef HAVE_SETRLIMIT
-    struct rlimit limit;
-
-    limit.rlim_cur = 0;
-    limit.rlim_max = 0;
-    if( !setrlimit( RLIMIT_CORE, &limit ) )
-       return 0;
-    if( errno != EINVAL && errno != ENOSYS )
-       log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
-#endif
-    return 1;
-#endif
-}
-
 
 /* For the sake of SELinux we want to restrict access through gpg to
    certain files we keep under our own control.  This function
@@ -168,7 +121,9 @@ register_secured_file (const char *fname)
   sf->dev = buf.st_dev;
   sf->next = secured_files;
   secured_files = sf;
-#endif /*ENABLE_SELINUX_HACKS*/
+#else /*!ENABLE_SELINUX_HACKS*/
+  (void)fname;
+#endif /*!ENABLE_SELINUX_HACKS*/
 }
 
 /* Remove a file registered as secure. */
@@ -199,7 +154,9 @@ unregister_secured_file (const char *fname)
           return;
         }
     }
-#endif /*ENABLE_SELINUX_HACKS*/
+#else /*!ENABLE_SELINUX_HACKS*/
+  (void)fname;
+#endif /*!ENABLE_SELINUX_HACKS*/
 }
 
 /* Return true if FD is corresponds to a secured file.  Using -1 for
@@ -229,7 +186,9 @@ is_secured_file (int fd)
       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
         return 1; /* Yes.  */
     }
-#endif /*ENABLE_SELINUX_HACKS*/
+#else /*!ENABLE_SELINUX_HACKS*/
+  (void)fd;
+#endif /*!ENABLE_SELINUX_HACKS*/
   return 0; /* No. */
 }
 
@@ -264,7 +223,9 @@ is_secured_filename (const char *fname)
       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
         return 1; /* Yes.  */
     }
-#endif /*ENABLE_SELINUX_HACKS*/
+#else /*!ENABLE_SELINUX_HACKS*/
+  (void)fname;
+#endif /*!ENABLE_SELINUX_HACKS*/
   return 0; /* No. */
 }
 
@@ -296,8 +257,7 @@ checksum_mpi (gcry_mpi_t a)
 {
   u16 csum;
   byte *buffer;
-  unsigned int nbytes;
-  unsigned int nbits;
+  size_t nbytes;
 
   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) )
     BUG ();
@@ -308,9 +268,7 @@ checksum_mpi (gcry_mpi_t a)
             gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes));
   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) )
     BUG ();
-  nbits = gcry_mpi_get_nbits (a);
-  csum = checksum_u16 (nbits);
-  csum += checksum (buffer, nbytes);
+  csum = checksum (buffer, nbytes);
   xfree (buffer);
   return csum;
 }
@@ -339,6 +297,10 @@ print_pubkey_algo_note( int algo )
                    gcry_pk_algo_name (algo));
        }
     }
+  else if (algo == 20)
+    {
+      log_info (_("WARNING: Elgamal sign+encrypt keys are deprecated\n"));
+    }
 }
 
 void
@@ -351,7 +313,7 @@ print_cipher_algo_note( int algo )
        {
          warn=1;
          log_info (_("WARNING: using experimental cipher algorithm %s\n"),
-                    gcry_cipher_algo_name (algo));
+                    openpgp_cipher_algo_name (algo));
        }
     }
 }
@@ -374,32 +336,57 @@ print_digest_algo_note( int algo )
               gcry_md_algo_name (algo));
 }
 
-/* Return a string which is used as a kind of process ID */
-const byte *
-get_session_marker( size_t *rlen )
+
+/* Map OpenPGP algo numbers to those used by Libgcrypt.  We need to do
+   this for algorithms we implemented in Libgcrypt after they become
+   part of OpenPGP.  */
+int
+map_cipher_openpgp_to_gcry (int algo)
 {
-  static byte marker[SIZEOF_UNSIGNED_LONG*2];
-  static int initialized;
-  
-  if ( !initialized )
+  switch (algo)
     {
-      volatile ulong aa, bb; /* We really want the uninitialized value. */
-      ulong a, b;
-      
-      initialized = 1;
-      /* Although this marker is guessable it is not easy to use this
-       * for a faked control packet because an attacker does not have
-       * enough control about the time the verification takes place.
-       * Of course, we could add just more random but than we need the
-       * random generator even for verification tasks - which does not
-       * make sense. */
-      a = aa ^ (ulong)getpid();
-      b = bb ^ (ulong)time(NULL);
-      memcpy ( marker, &a, SIZEOF_UNSIGNED_LONG );
-      memcpy ( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
+    case CIPHER_ALGO_CAMELLIA128: return 310; 
+    case CIPHER_ALGO_CAMELLIA192: return 311; 
+    case CIPHER_ALGO_CAMELLIA256: return 312; 
+    default: return algo;
+    }
+}
+
+/* The inverse fucntion of above.  */
+static int
+map_cipher_gcry_to_openpgp (int algo)
+{
+  switch (algo)
+    {
+    case 310: return CIPHER_ALGO_CAMELLIA128;
+    case 311: return CIPHER_ALGO_CAMELLIA192;
+    case 312: return CIPHER_ALGO_CAMELLIA256;
+    default: return algo;
+    }
+}
+
+
+/* Return the block length of an OpenPGP cipher algorithm.  */
+int 
+openpgp_cipher_blocklen (int algo)
+{
+  /* We use the numbers from OpenPGP to be sure that we get the right
+     block length.  This is so that the packet parsing code works even
+     for unknown algorithms (for which we assume 8 due to tradition).
+
+     NOTE: If you change the the returned blocklen above 16, check
+     the callers because they may use a fixed size buffer of that
+     size. */
+  switch (algo)
+    {
+    case 7: case 8: case 9: /* AES */
+    case 10: /* Twofish */
+    case 11: case 12: case 13: /* Camellia */
+      return 16;
+
+    default:
+      return 8;
     }
-  *rlen = sizeof(marker);
-  return marker;
 }
 
 /****************
@@ -409,14 +396,29 @@ get_session_marker( size_t *rlen )
 int
 openpgp_cipher_test_algo( int algo )
 {
-  if ( algo < 0 || algo > 110 )
+  /* (5 and 6 are marked reserved by rfc4880.)  */
+  if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 )
     return gpg_error (GPG_ERR_CIPHER_ALGO);
-  return gcry_cipher_test_algo (algo);
+
+  return gcry_cipher_test_algo (map_cipher_openpgp_to_gcry (algo));
+}
+
+/* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a
+   string representation of the algorithm name.  For unknown algorithm
+   IDs this function returns "?".  */
+const char *
+openpgp_cipher_algo_name (int algo) 
+{
+  return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
 }
 
 int
 openpgp_pk_test_algo( int algo )
 {
+  /* Dont't allow type 20 keys unless in rfc2440 mode.  */
+  if (!RFC2440 && algo == 20)
+    return gpg_error (GPG_ERR_PUBKEY_ALGO);
+    
   if (algo == GCRY_PK_ELG_E)
     algo = GCRY_PK_ELG;
 
@@ -428,8 +430,11 @@ openpgp_pk_test_algo( int algo )
 int
 openpgp_pk_test_algo2( int algo, unsigned int use )
 {
-  int use_buf = use;
-  size_t sizeof_use_buf = sizeof (use_buf);
+  size_t use_buf = use;
+
+  /* Dont't allow type 20 keys unless in rfc2440 mode.  */
+  if (!RFC2440 && algo == 20)
+    return gpg_error (GPG_ERR_PUBKEY_ALGO);
 
   if (algo == GCRY_PK_ELG_E)
     algo = GCRY_PK_ELG;
@@ -437,8 +442,7 @@ openpgp_pk_test_algo2( int algo, unsigned int use )
   if (algo < 0 || algo > 110)
     return gpg_error (GPG_ERR_PUBKEY_ALGO);
 
-  return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO,
-                            &use_buf, &sizeof_use_buf);
+  return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &use_buf);
 }
 
 int 
@@ -458,6 +462,10 @@ openpgp_pk_algo_usage ( int algo )
       case PUBKEY_ALGO_RSA_S:
           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
           break;
+      case PUBKEY_ALGO_ELGAMAL:
+          if (RFC2440)
+             use = PUBKEY_USAGE_ENC;
+          break;
       case PUBKEY_ALGO_ELGAMAL_E:
           use = PUBKEY_USAGE_ENC;
           break;
@@ -473,7 +481,12 @@ openpgp_pk_algo_usage ( int algo )
 int
 openpgp_md_test_algo( int algo )
 {
-  if (algo < 0 || algo > 110)
+  /* Note: If the list of actual supported OpenPGP algorithms changes,
+     make sure that our hard coded values at
+     print_status_begin_signing() gets updated. */
+  /* 4, 5, 6, 7 are defined by rfc2440 but will be removed from the
+     next revision of the standard.  */
+  if (algo < 0 || algo > 110 || (algo >= 4 && algo <= 7))
     return gpg_error (GPG_ERR_DIGEST_ALGO);
   return gcry_md_test_algo (algo);
 }
@@ -495,7 +508,9 @@ idea_cipher_warn(int show)
 }
 #endif
 
-static unsigned long get_signature_count(PKT_secret_key *sk)
+
+static unsigned long 
+get_signature_count (PKT_secret_key *sk)
 {
 #ifdef ENABLE_CARD_SUPPORT
   if(sk && sk->is_protected && sk->protect.s2k.mode==1002)
@@ -534,8 +549,6 @@ pct_expando(const char *string,struct expando_args *args)
 
   while(*ch!='\0')
     {
-      char *str=NULL;
-
       if(!done)
        {
          /* 8192 is way bigger than we'll need here */
@@ -644,22 +657,46 @@ pct_expando(const char *string,struct expando_args *args)
              }
              break;
 
-           case 't': /* e.g. "jpg" */
-             str=image_type_to_string(args->imagetype,0);
-             /* fall through */
-
-           case 'T': /* e.g. "image/jpeg" */
-             if(str==NULL)
-               str=image_type_to_string(args->imagetype,2);
-
-             if(idx+strlen(str)<maxlen)
+           case 'v': /* validity letters */
+             if(args->validity_info && idx+1<maxlen)
                {
-                 strcpy(&ret[idx],str);
-                 idx+=strlen(str);
+                 ret[idx++]=args->validity_info;
+                 ret[idx]='\0';
                  done=1;
                }
              break;
 
+             /* The text string types */
+           case 't':
+           case 'T':
+           case 'V':
+             {
+               const char *str=NULL;
+
+               switch(*(ch+1))
+                 {
+                 case 't': /* e.g. "jpg" */
+                   str=image_type_to_string(args->imagetype,0);
+                   break;
+                 
+                 case 'T': /* e.g. "image/jpeg" */
+                   str=image_type_to_string(args->imagetype,2);
+                   break;
+
+                 case 'V': /* e.g. "full", "expired", etc. */
+                   str=args->validity_string;
+                   break;
+                 }
+
+               if(str && idx+strlen(str)<maxlen)
+                 {
+                   strcpy(&ret[idx],str);
+                   idx+=strlen(str);
+                   done=1;
+                 }
+             }
+             break;
+
            case '%':
              if(idx+1<maxlen)
                {
@@ -739,6 +776,67 @@ deprecated_command (const char *name)
 }
 
 
+void
+obsolete_option (const char *configname, unsigned int configlineno, 
+                 const char *name)
+{
+  if(configname)
+    log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
+              configname, configlineno, name);
+  else
+    log_info (_("WARNING: \"%s\" is an obsolete option - it has no effect\n"),
+              name);
+}
+
+
+/*
+ * Wrapper around gcry_cipher_map_name to provide a fallback using the
+ * "Sn" syntax as used by the preference strings.
+ */
+int 
+string_to_cipher_algo (const char *string) 
+{ 
+  int val;
+
+  val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
+  if (!val && string && (string[0]=='S' || string[0]=='s'))
+    {
+      char *endptr;
+
+      string++;
+      val = strtol (string, &endptr, 10);
+      if (!*string || *endptr || openpgp_cipher_test_algo (val))
+        val = 0;
+    }
+
+  return val;
+}
+
+/*
+ * Wrapper around gcry_md_map_name to provide a fallback using the
+ * "Hn" syntax as used by the preference strings.
+ */
+int 
+string_to_digest_algo (const char *string) 
+{ 
+  int val;
+
+  val = gcry_md_map_name (string);
+  if (!val && string && (string[0]=='H' || string[0]=='h'))
+    {
+      char *endptr;
+
+      string++;
+      val = strtol (string, &endptr, 10);
+      if (!*string || *endptr || openpgp_md_test_algo (val))
+        val = 0;
+    }
+
+  return val;
+}
+
+
+
 const char *
 compress_algo_to_string(int algo)
 {
@@ -771,7 +869,7 @@ compress_algo_to_string(int algo)
 int
 string_to_compress_algo(const char *string)
 {
-  /* NOTE TO TRANSLATOR: See doc/TRANSLATE about this string. */
+  /* TRANSLATORS: See doc/TRANSLATE about this string. */
   if(match_multistr(_("uncompressed|none"),string))
     return 0;
   else if(ascii_strcasecmp(string,"uncompressed")==0)
@@ -842,47 +940,64 @@ default_compress_algo(void)
 const char *
 compliance_option_string(void)
 {
+  char *ver="???";
+
   switch(opt.compliance)
     {
-    case CO_RFC2440:
-      return "--openpgp";
-    case CO_PGP2:
-      return "--pgp2";
-    case CO_PGP6:
-      return "--pgp6";
-    case CO_PGP7:
-      return "--pgp7";
-    case CO_PGP8:
-      return "--pgp8";
-    default:
-      return "???";
+    case CO_GNUPG:   return "--gnupg";
+    case CO_RFC4880: return "--openpgp";
+    case CO_RFC2440: return "--rfc2440";
+    case CO_RFC1991: return "--rfc1991";
+    case CO_PGP2:    return "--pgp2";
+    case CO_PGP6:    return "--pgp6";
+    case CO_PGP7:    return "--pgp7";
+    case CO_PGP8:    return "--pgp8";
     }
+
+  return ver;
 }
 
-static const char *
-compliance_string(void)
+void
+compliance_failure(void)
 {
+  char *ver="???";
+
   switch(opt.compliance)
     {
+    case CO_GNUPG:
+      ver="GnuPG";
+      break;
+
+    case CO_RFC4880:
+      ver="OpenPGP";
+      break;
+
     case CO_RFC2440:
-      return "OpenPGP";
+      ver="OpenPGP (older)";
+      break;
+
+    case CO_RFC1991:
+      ver="old PGP";
+      break;
+
     case CO_PGP2:
-      return "PGP 2.x";
+      ver="PGP 2.x";
+      break;
+
     case CO_PGP6:
-      return "PGP 6.x";
+      ver="PGP 6.x";
+      break;
+
     case CO_PGP7:
-      return "PGP 7.x";
+      ver="PGP 7.x";
+      break;
+
     case CO_PGP8:
-      return "PGP 8.x";
-    default:
-      return "???";
+      ver="PGP 8.x";
+      break;
     }
-}
 
-void
-compliance_failure(void)
-{
-  log_info(_("this message may not be usable by %s\n"),compliance_string());
+  log_info(_("this message may not be usable by %s\n"),ver);
   opt.compliance=CO_GNUPG;
 }
 
@@ -1091,39 +1206,16 @@ parse_options(char *str,unsigned int *options,
 }
 
 
-/* Return a new malloced string by unescaping the string S.  Escaping
-   is percent escaping and '+'/space mapping.  A binary nul will
-   silently be replaced by a 0xFF. */
-char *
-unescape_percent_string (const unsigned char *s)
-{
-  char *buffer, *d;
-
-  buffer = d = xmalloc (strlen (s)+1);
-  while (*s)
-    {
-      if (*s == '%' && s[1] && s[2])
-        { 
-          s++;
-          *d = xtoi_2 (s);
-          if (!*d)
-            *d = '\xff';
-          d++;
-          s += 2;
-        }
-      else if (*s == '+')
-        {
-          *d++ = ' ';
-          s++;
-        }
-      else
-        *d++ = *s++;
-    }
-  *d = 0; 
-  return buffer;
-}
-
-
+/* Check whether the string has characters not valid in an RFC-822
+   address.  To cope with OpenPGP we ignore non-ascii characters
+   so that for example umlauts are legal in an email address.  An
+   OpenPGP user ID must be utf-8 encoded but there is no strict
+   requirement for RFC-822.  Thus to avoid IDNA encoding we put the
+   address verbatim as utf-8 into the user ID under the assumption
+   that mail programs handle IDNA at a lower level and take OpenPGP
+   user IDs as utf-8.  Note that we can't do an utf-8 encoding
+   checking here because in keygen.c this function is called with the
+   native encoding and native to utf-8 encoding is only done  later.  */
 int
 has_invalid_email_chars (const char *s)
 {
@@ -1133,8 +1225,8 @@ has_invalid_email_chars (const char *s)
 
   for ( ; *s; s++ ) 
     {
-      if ( *s & 0x80 )
-        return 1;
+      if ( (*s & 0x80) )
+        continue; /* We only care about ASCII.  */
       if ( *s == '@' )
         at_seen=1;
       else if ( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) )
@@ -1162,83 +1254,6 @@ is_valid_mailbox (const char *name)
 }
 
 
-/* This is a helper function to load a Windows function from either of
-   one DLLs. */
-#ifdef HAVE_W32_SYSTEM
-static HRESULT
-w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
-{
-  static int initialized;
-  static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
-
-  if (!initialized)
-    {
-      static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
-      void *handle;
-      int i;
-
-      initialized = 1;
-
-      for (i=0, handle = NULL; !handle && dllnames[i]; i++)
-        {
-          handle = dlopen (dllnames[i], RTLD_LAZY);
-          if (handle)
-            {
-              func = dlsym (handle, "SHGetFolderPathA");
-              if (!func)
-                {
-                  dlclose (handle);
-                  handle = NULL;
-                }
-            }
-        }
-    }
-
-  if (func)
-    return func (a,b,c,d,e);
-  else
-    return -1;
-}
-#endif /*HAVE_W32_SYSTEM*/
-
-
-/* Return the name of the libexec directory.  The name is allocated in
-   a static area on the first use.  This function won't fail. */
-const char *
-get_libexecdir (void)
-{
-#ifdef HAVE_W32_SYSTEM
-  static int got_dir;
-  static char dir[MAX_PATH+5];
-
-  if (!got_dir)
-    {
-      char *p;
-
-      if ( !GetModuleFileName ( NULL, dir, MAX_PATH) )
-        {
-          log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0));
-          *dir = 0;
-        }
-      got_dir = 1;
-      p = strrchr (dir, DIRSEP_C);
-      if (p)
-        *p = 0;
-      else
-        {
-          log_debug ("bad filename `%s' returned for this process\n", dir);
-          *dir = 0; 
-        }
-    }
-
-  if (*dir)
-    return dir;
-  /* Fallback to the hardwired value. */
-#endif /*HAVE_W32_SYSTEM*/
-
-  return GNUPG_LIBEXECDIR;
-}
-
 /* Similar to access(2), but uses PATH to find the file. */
 int
 path_access(const char *file,int mode)