Use macros for iobuf ioctls.
[gnupg.git] / g10 / misc.c
index f02601f..f34e1e3 100644 (file)
@@ -1,6 +1,6 @@
 /* misc.c - miscellaneous functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- *               2005, 2006, 2007 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.
  *
@@ -121,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. */
@@ -152,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
@@ -182,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. */
 }
 
@@ -217,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. */
 }
 
@@ -289,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
@@ -301,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));
        }
     }
 }
@@ -324,6 +336,59 @@ print_digest_algo_note( int algo )
               gcry_md_algo_name (algo));
 }
 
+
+/* 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)
+{
+  switch (algo)
+    {
+    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;
+    }
+}
+
 /****************
  * Wrapper around the libgcrypt function with additonal checks on
  * the OpenPGP contraints for the algo ID.
@@ -331,15 +396,29 @@ print_digest_algo_note( int algo )
 int
 openpgp_cipher_test_algo( int algo )
 {
-  /* 5 and 6 are marked reserved by rfc2440bis.  */
+  /* (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;
 
@@ -353,6 +432,10 @@ openpgp_pk_test_algo2( int algo, unsigned int use )
 {
   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;
 
@@ -379,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;
@@ -423,15 +510,16 @@ idea_cipher_warn(int show)
 
 
 static unsigned long 
-get_signature_count (PKT_secret_key *sk)
+get_signature_count (PKT_public_key *pk)
 {
 #ifdef ENABLE_CARD_SUPPORT
-  if(sk && sk->is_protected && sk->protect.s2k.mode==1002)
-    {
-      struct agent_card_info_s info;
-      if(agent_scd_getattr("SIG-COUNTER",&info)==0)
-       return info.sig_counter;
-    }  
+  /* FIXME: Need to call the agent.  */
+  /* if(sk && sk->is_protected && sk->protect.s2k.mode==1002) */
+  /*   { */
+  /*     struct agent_card_info_s info; */
+  /*     if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
+  /*       return info.sig_counter; */
+  /*   }   */
 #endif
 
   /* How to do this without a card? */
@@ -452,18 +540,16 @@ pct_expando(const char *string,struct expando_args *args)
   if(args->pk)
     keyid_from_pk(args->pk,pk_keyid);
 
-  if(args->sk)
-    keyid_from_sk(args->sk,sk_keyid);
+  if(args->pksk)
+    keyid_from_pk (args->pksk, sk_keyid);
 
   /* This is used so that %k works in photoid command strings in
      --list-secret-keys (which of course has a sk, but no pk). */
-  if(!args->pk && args->sk)
-    keyid_from_sk(args->sk,pk_keyid);
+  if(!args->pk && args->pksk)
+    keyid_from_pk (args->pksk, pk_keyid);
 
   while(*ch!='\0')
     {
-      char *str=NULL;
-
       if(!done)
        {
          /* 8192 is way bigger than we'll need here */
@@ -521,7 +607,7 @@ pct_expando(const char *string,struct expando_args *args)
            case 'c': /* signature count from card, if any. */
              if(idx+10<maxlen)
                {
-                 sprintf(&ret[idx],"%lu",get_signature_count(args->sk));
+                 sprintf (&ret[idx],"%lu", get_signature_count (args->pksk));
                  idx+=strlen(&ret[idx]);
                  done=1;
                }             
@@ -535,28 +621,31 @@ pct_expando(const char *string,struct expando_args *args)
                size_t len;
                int i;
 
-               if((*(ch+1))=='p' && args->sk)
+               if((*(ch+1))=='p' && args->pksk)
                  {
-                   if(args->sk->is_primary)
-                     fingerprint_from_sk(args->sk,array,&len);
-                   else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
+                   if(args->pksk->is_primary)
+                     fingerprint_from_pk (args->pksk, array, &len);
+                   else if (args->pksk->main_keyid[0]
+                             || args->pksk->main_keyid[1])
                      {
+                        /* FIXME: Document teh code and check whether
+                           it is still needed.  */
                        PKT_public_key *pk=
                          xmalloc_clear(sizeof(PKT_public_key));
 
-                       if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
-                         fingerprint_from_pk(pk,array,&len);
+                       if (!get_pubkey_fast (pk,args->pksk->main_keyid))
+                         fingerprint_from_pk (pk, array, &len);
                        else
-                         memset(array,0,(len=MAX_FINGERPRINT_LEN));
-                       free_public_key(pk);
+                         memset (array, 0, (len=MAX_FINGERPRINT_LEN));
+                       free_public_key (pk);
                      }
                    else
                      memset(array,0,(len=MAX_FINGERPRINT_LEN));
                  }
                else if((*(ch+1))=='f' && args->pk)
-                 fingerprint_from_pk(args->pk,array,&len);
-               else if((*(ch+1))=='g' && args->sk)
-                 fingerprint_from_sk(args->sk,array,&len);
+                 fingerprint_from_pk (args->pk, array, &len);
+               else if((*(ch+1))=='g' && args->pksk)
+                 fingerprint_from_pk (args->pksk, array, &len);
                else
                  memset(array,0,(len=MAX_FINGERPRINT_LEN));
 
@@ -572,22 +661,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)
                {
@@ -689,7 +802,7 @@ string_to_cipher_algo (const char *string)
 { 
   int val;
 
-  val = gcry_cipher_map_name (string);
+  val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
   if (!val && string && (string[0]=='S' || string[0]=='s'))
     {
       char *endptr;
@@ -1097,39 +1210,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)
 {
@@ -1139,8 +1229,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 == '+' ) )