Pass DBUS_SESSION_BUS_ADDRESS for gnome3
[gnupg.git] / common / userids.c
index 9a072dd..e1304be 100644 (file)
@@ -4,12 +4,22 @@
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of either
  *
- * GnuPG is distributed in the hope that it will be useful,
+ *   - the GNU Lesser General Public License as published by the Free
+ *     Software Foundation; either version 3 of the License, or (at
+ *     your option) any later version.
+ *
+ * or
+ *
+ *   - the GNU General Public License as published by the Free
+ *     Software Foundation; either version 2 of the License, or (at
+ *     your option) any later version.
+ *
+ * or both in parallel, as here.
+ *
+ * This file is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* This file implements a few utility functions useful when working
-   with canonical encrypted S-expresions (i.e. not the S-exprssion
-   objects from libgcrypt).  */
-
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -32,7 +38,7 @@
 
 
 /* Parse the user-id NAME and build a search description for it.
- * Returns 0 on succdess or an error code.  DESC may be NULL to merely
+ * Returns 0 on success or an error code.  DESC may be NULL to merely
  * check the validity of a user-id.
  *
  * Some used rules:
@@ -43,8 +49,8 @@
  *   must be in the range 0..9), this is considered a fingerprint.
  * - If the username starts with a left angle, we assume it is a complete
  *   email address and look only at this part.
- * - If the username starts with a colon we assume it is a unified 
- *   key specfification. 
+ * - If the username starts with a colon we assume it is a unified
+ *   key specfification.
  * - If the username starts with a '.', we assume it is the ending
  *   part of an email address
  * - If the username starts with an '@', we assume it is a part of an
  */
 
 gpg_error_t
-classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
+classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
 {
   const char *s;
   int hexprefix = 0;
   int hexlength;
-  int mode = 0;   
+  int mode = 0;
   KEYDB_SEARCH_DESC dummy_desc;
 
   if (!desc)
     desc = &dummy_desc;
-    
+
   /* Clear the structure so that the mode field is set to zero unless
      we set it to the correct value right at the end of this
      function. */
@@ -81,7 +87,7 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
   for(s = name; *s && spacep (s); s++ )
     ;
 
-  switch (*s) 
+  switch (*s)
     {
     case 0:  /* Empty string is an error.  */
       return gpg_error (GPG_ERR_INV_USER_ID);
@@ -95,7 +101,12 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
 
     case '<': /* An email address.  */
       mode = KEYDB_SEARCH_MODE_MAIL;
-      s++;
+      /* FIXME: The keyring code in g10 assumes that the mail name is
+         prefixed with an '<'.  However the keybox code used for sm/
+         assumes it has been removed.  For now we use this simple hack
+         to overcome the problem.  */
+      if (!openpgp_hack)
+        s++;
       desc->u.name = s;
       break;
 
@@ -133,19 +144,19 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
       break;
 
     case '#': /* S/N with optional issuer id or just issuer id.  */
-      { 
+      {
         const char *si;
-        
+
         s++;
         if ( *s == '/')
           { /* "#/" indicates an issuer's DN.  */
             s++;
             if (!*s || spacep (s)) /* No DN or prefixed with a space.  */
-              return gpg_error (GPG_ERR_INV_USER_ID); 
+              return gpg_error (GPG_ERR_INV_USER_ID);
             desc->u.name = s;
             mode = KEYDB_SEARCH_MODE_ISSUER;
           }
-        else 
+        else
           { /* Serialnumber + optional issuer ID.  */
             for (si=s; *si && *si != '/'; si++)
               {
@@ -170,10 +181,10 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
       break;
 
     case ':': /* Unified fingerprint. */
-      {  
+      {
         const char *se, *si;
         int i;
-        
+
         se = strchr (++s,':');
         if (!se)
           return gpg_error (GPG_ERR_INV_USER_ID);
@@ -184,21 +195,21 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
           }
         if (i != 32 && i != 40)
           return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr.  */
-        for (i=0,si=s; si < se; i++, si +=2) 
+        for (i=0,si=s; si < se; i++, si +=2)
           desc->u.fpr[i] = hextobyte(si);
         for (; i < 20; i++)
           desc->u.fpr[i]= 0;
         s = se + 1;
         mode = KEYDB_SEARCH_MODE_FPR;
-      } 
+      }
       break;
 
     case '&': /* Keygrip*/
-      {  
+      {
         if (hex2bin (s+1, desc->u.grip, 20) < 0)
           return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
         mode = KEYDB_SEARCH_MODE_KEYGRIP;
-      } 
+      }
       break;
 
     default:
@@ -214,33 +225,33 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
           desc->exact = 1;
           hexlength++; /* Just for the following check.  */
         }
-      
+
       /* Check if a hexadecimal number is terminated by EOS or blank.  */
-      if (hexlength && s[hexlength] && !spacep (s+hexlength)) 
+      if (hexlength && s[hexlength] && !spacep (s+hexlength))
         {
           if (hexprefix) /* A "0x" prefix without a correct
                             termination is an error.  */
-            return gpg_error (GPG_ERR_INV_USER_ID); 
+            return gpg_error (GPG_ERR_INV_USER_ID);
           /* The first characters looked like a hex number, but the
              entire string is not.  */
-          hexlength = 0;  
+          hexlength = 0;
         }
-      
+
       if (desc->exact)
         hexlength--; /* Remove the bang.  */
 
       if (hexlength == 8
           || (!hexprefix && hexlength == 9 && *s == '0'))
-        { 
+        {
           /* Short keyid.  */
           if (hexlength == 9)
-            s++; 
+            s++;
           desc->u.kid[1] = strtoul( s, NULL, 16 );
           mode = KEYDB_SEARCH_MODE_SHORT_KID;
         }
       else if (hexlength == 16
                || (!hexprefix && hexlength == 17 && *s == '0'))
-        { 
+        {
           /* Long keyid.  */
           char buf[9];
           if (hexlength == 17)
@@ -252,13 +263,13 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
         }
       else if (hexlength == 32
                || (!hexprefix && hexlength == 33 && *s == '0'))
-        { 
+        {
           /* MD5 fingerprint.  */
           int i;
           if (hexlength == 33)
             s++;
-          memset (desc->u.fpr+16, 0, 4); 
-          for (i=0; i < 16; i++, s+=2) 
+          memset (desc->u.fpr+16, 0, 4);
+          for (i=0; i < 16; i++, s+=2)
             {
               int c = hextobyte(s);
               if (c == -1)
@@ -269,12 +280,12 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
         }
       else if (hexlength == 40
                || (!hexprefix && hexlength == 41 && *s == '0'))
-        { 
+        {
           /* SHA1/RMD160 fingerprint.  */
           int i;
           if (hexlength == 41)
             s++;
-          for (i=0; i < 20; i++, s+=2) 
+          for (i=0; i < 20; i++, s+=2)
             {
               int c = hextobyte(s);
               if (c == -1)
@@ -284,16 +295,16 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
           mode = KEYDB_SEARCH_MODE_FPR20;
         }
       else if (!hexprefix)
-        { 
+        {
           /* The fingerprint in an X.509 listing is often delimited by
              colons, so we try to single this case out. */
           mode = 0;
           hexlength = strspn (s, ":0123456789abcdefABCDEF");
-          if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength))) 
+          if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
             {
               int i;
 
-              for (i=0; i < 20; i++, s += 3) 
+              for (i=0; i < 20; i++, s += 3)
                 {
                   int c = hextobyte(s);
                   if (c == -1 || (i < 19 && s[2] != ':'))
@@ -303,20 +314,63 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc)
               if (i == 20)
                 mode = KEYDB_SEARCH_MODE_FPR20;
             }
+          if (!mode)
+            {
+              /* Still not found.  Now check for a space separated
+                 OpenPGP v4 fingerprint like:
+                   8061 5870 F5BA D690 3336  86D0 F2AD 85AC 1E42 B367
+                 or
+                   8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
+               */
+              hexlength = strspn (s, " 0123456789abcdefABCDEF");
+              if (s[hexlength] && s[hexlength] != ' ')
+                hexlength = 0; /* Followed by non-space.  */
+              while (hexlength && s[hexlength-1] == ' ')
+                hexlength--;   /* Trim trailing spaces.  */
+              if ((hexlength == 49 || hexlength == 50)
+                  && (!s[hexlength] || s[hexlength] == ' '))
+                {
+                  int i, c;
+
+                  for (i=0; i < 20; i++)
+                    {
+                      if (i && !(i % 2))
+                        {
+                          if (*s != ' ')
+                            break;
+                          s++;
+                          /* Skip the double space in the middle but
+                             don't require it to help copying
+                             fingerprints from sources which fold
+                             multiple space to one.  */
+                          if (i == 10 && *s == ' ')
+                            s++;
+                        }
+
+                      c = hextobyte(s);
+                      if (c == -1)
+                        break;
+                      desc->u.fpr[i] = c;
+                      s += 2;
+                    }
+                  if (i == 20)
+                    mode = KEYDB_SEARCH_MODE_FPR20;
+                }
+            }
           if (!mode) /* Default to substring search.  */
-            { 
+            {
               desc->exact = 0;
               desc->u.name = s;
-              mode = KEYDB_SEARCH_MODE_SUBSTR; 
+              mode = KEYDB_SEARCH_MODE_SUBSTR;
             }
         }
       else
-       { 
+       {
           /* Hex number with a prefix but with a wrong length.  */
           return gpg_error (GPG_ERR_INV_USER_ID);
         }
     }
-  
+
   desc->mode = mode;
   return 0;
 }