LCOV - code coverage report
Current view: top level - common - userids.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 67 169 39.6 %
Date: 2015-11-05 17:10:59 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /* userids.c - Utility functions for user ids.
       2             :  * Copyright (C) 2001, 2003, 2004, 2006,
       3             :  *               2009 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : #include <stdio.h>
      33             : #include <stdlib.h>
      34             : #include <string.h>
      35             : 
      36             : #include "util.h"
      37             : #include "userids.h"
      38             : 
      39             : 
      40             : /* Parse the user-id NAME and build a search description for it.
      41             :  * Returns 0 on success or an error code.  DESC may be NULL to merely
      42             :  * check the validity of a user-id.
      43             :  *
      44             :  * Some used rules:
      45             :  * - If the username starts with 8,9,16 or 17 hex-digits (the first one
      46             :  *   must be in the range 0..9), this is considered a keyid; depending
      47             :  *   on the length a short or complete one.
      48             :  * - If the username starts with 32,33,40 or 41 hex-digits (the first one
      49             :  *   must be in the range 0..9), this is considered a fingerprint.
      50             :  * - If the username starts with a left angle, we assume it is a complete
      51             :  *   email address and look only at this part.
      52             :  * - If the username starts with a colon we assume it is a unified
      53             :  *   key specfification.
      54             :  * - If the username starts with a '.', we assume it is the ending
      55             :  *   part of an email address
      56             :  * - If the username starts with an '@', we assume it is a part of an
      57             :  *   email address
      58             :  * - If the userid start with an '=' an exact compare is done.
      59             :  * - If the userid starts with a '*' a case insensitive substring search is
      60             :  *   done (This is the default).
      61             :  * - If the userid starts with a '+' we will compare individual words
      62             :  *   and a match requires that all the words are in the userid.
      63             :  *   Words are delimited by white space or "()<>[]{}.@-+_,;/&!"
      64             :  *   (note that you can't search for these characters). Compare
      65             :  *   is not case sensitive.
      66             :  * - If the userid starts with a '&' a 40 hex digits keygrip is expected.
      67             :  */
      68             : 
      69             : gpg_error_t
      70         419 : classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
      71             : {
      72             :   const char *s;
      73         419 :   int hexprefix = 0;
      74             :   int hexlength;
      75         419 :   int mode = 0;
      76             :   KEYDB_SEARCH_DESC dummy_desc;
      77             : 
      78         419 :   if (!desc)
      79           0 :     desc = &dummy_desc;
      80             : 
      81             :   /* Clear the structure so that the mode field is set to zero unless
      82             :      we set it to the correct value right at the end of this
      83             :      function. */
      84         419 :   memset (desc, 0, sizeof *desc);
      85             : 
      86             :   /* Skip leading spaces.  */
      87         419 :   for(s = name; *s && spacep (s); s++ )
      88             :     ;
      89             : 
      90         419 :   switch (*s)
      91             :     {
      92             :     case 0:  /* Empty string is an error.  */
      93           0 :       return gpg_error (GPG_ERR_INV_USER_ID);
      94             : 
      95             :     case '.': /* An email address, compare from end.  Note that this
      96             :                  has not yet been implemented in the search code.  */
      97           0 :       mode = KEYDB_SEARCH_MODE_MAILEND;
      98           0 :       s++;
      99           0 :       desc->u.name = s;
     100           0 :       break;
     101             : 
     102             :     case '<': /* An email address.  */
     103           0 :       mode = KEYDB_SEARCH_MODE_MAIL;
     104             :       /* FIXME: The keyring code in g10 assumes that the mail name is
     105             :          prefixed with an '<'.  However the keybox code used for sm/
     106             :          assumes it has been removed.  For now we use this simple hack
     107             :          to overcome the problem.  */
     108           0 :       if (!openpgp_hack)
     109           0 :         s++;
     110           0 :       desc->u.name = s;
     111           0 :       break;
     112             : 
     113             :     case '@':  /* Part of an email address.  */
     114           0 :       mode = KEYDB_SEARCH_MODE_MAILSUB;
     115           0 :       s++;
     116           0 :       desc->u.name = s;
     117           0 :       break;
     118             : 
     119             :     case '=':  /* Exact compare.  */
     120           0 :       mode = KEYDB_SEARCH_MODE_EXACT;
     121           0 :       s++;
     122           0 :       desc->u.name = s;
     123           0 :       break;
     124             : 
     125             :     case '*':  /* Case insensitive substring search.  */
     126           0 :       mode = KEYDB_SEARCH_MODE_SUBSTR;
     127           0 :       s++;
     128           0 :       desc->u.name = s;
     129           0 :       break;
     130             : 
     131             :     case '+':  /* Compare individual words.  Note that this has not
     132             :                   yet been implemented in the search code.  */
     133           0 :       mode = KEYDB_SEARCH_MODE_WORDS;
     134           0 :       s++;
     135           0 :       desc->u.name = s;
     136           0 :       break;
     137             : 
     138             :     case '/': /* Subject's DN.  */
     139           0 :       s++;
     140           0 :       if (!*s || spacep (s)) /* No DN or prefixed with a space.  */
     141           0 :         return gpg_error (GPG_ERR_INV_USER_ID);
     142           0 :       desc->u.name = s;
     143           0 :       mode = KEYDB_SEARCH_MODE_SUBJECT;
     144           0 :       break;
     145             : 
     146             :     case '#': /* S/N with optional issuer id or just issuer id.  */
     147             :       {
     148             :         const char *si;
     149             : 
     150           0 :         s++;
     151           0 :         if ( *s == '/')
     152             :           { /* "#/" indicates an issuer's DN.  */
     153           0 :             s++;
     154           0 :             if (!*s || spacep (s)) /* No DN or prefixed with a space.  */
     155           0 :               return gpg_error (GPG_ERR_INV_USER_ID);
     156           0 :             desc->u.name = s;
     157           0 :             mode = KEYDB_SEARCH_MODE_ISSUER;
     158             :           }
     159             :         else
     160             :           { /* Serialnumber + optional issuer ID.  */
     161           0 :             for (si=s; *si && *si != '/'; si++)
     162             :               {
     163             :                  /* Check for an invalid digit in the serial number. */
     164           0 :                 if (!strchr("01234567890abcdefABCDEF", *si))
     165           0 :                   return gpg_error (GPG_ERR_INV_USER_ID);
     166             :               }
     167           0 :             desc->sn = (const unsigned char*)s;
     168           0 :             desc->snlen = -1;
     169           0 :             if (!*si)
     170           0 :               mode = KEYDB_SEARCH_MODE_SN;
     171             :             else
     172             :               {
     173           0 :                 s = si+1;
     174           0 :                 if (!*s || spacep (s))  /* No DN or prefixed with a space.  */
     175           0 :                   return gpg_error (GPG_ERR_INV_USER_ID);
     176           0 :                 desc->u.name = s;
     177           0 :                 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
     178             :               }
     179             :           }
     180             :       }
     181           0 :       break;
     182             : 
     183             :     case ':': /* Unified fingerprint. */
     184             :       {
     185             :         const char *se, *si;
     186             :         int i;
     187             : 
     188           0 :         se = strchr (++s,':');
     189           0 :         if (!se)
     190           0 :           return gpg_error (GPG_ERR_INV_USER_ID);
     191           0 :         for (i=0,si=s; si < se; si++, i++ )
     192             :           {
     193           0 :             if (!strchr("01234567890abcdefABCDEF", *si))
     194           0 :               return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid digit.  */
     195             :           }
     196           0 :         if (i != 32 && i != 40)
     197           0 :           return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr.  */
     198           0 :         for (i=0,si=s; si < se; i++, si +=2)
     199           0 :           desc->u.fpr[i] = hextobyte(si);
     200           0 :         for (; i < 20; i++)
     201           0 :           desc->u.fpr[i]= 0;
     202           0 :         s = se + 1;
     203           0 :         mode = KEYDB_SEARCH_MODE_FPR;
     204             :       }
     205           0 :       break;
     206             : 
     207             :     case '&': /* Keygrip*/
     208             :       {
     209           0 :         if (hex2bin (s+1, desc->u.grip, 20) < 0)
     210           0 :           return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
     211           0 :         mode = KEYDB_SEARCH_MODE_KEYGRIP;
     212             :       }
     213           0 :       break;
     214             : 
     215             :     default:
     216         419 :       if (s[0] == '0' && s[1] == 'x')
     217             :         {
     218          95 :           hexprefix = 1;
     219          95 :           s += 2;
     220             :         }
     221             : 
     222         419 :       hexlength = strspn(s, "0123456789abcdefABCDEF");
     223         419 :       if (hexlength >= 8 && s[hexlength] =='!')
     224             :         {
     225           0 :           desc->exact = 1;
     226           0 :           hexlength++; /* Just for the following check.  */
     227             :         }
     228             : 
     229             :       /* Check if a hexadecimal number is terminated by EOS or blank.  */
     230         419 :       if (hexlength && s[hexlength] && !spacep (s+hexlength))
     231             :         {
     232           0 :           if (hexprefix) /* A "0x" prefix without a correct
     233             :                             termination is an error.  */
     234           0 :             return gpg_error (GPG_ERR_INV_USER_ID);
     235             :           /* The first characters looked like a hex number, but the
     236             :              entire string is not.  */
     237           0 :           hexlength = 0;
     238             :         }
     239             : 
     240         419 :       if (desc->exact)
     241           0 :         hexlength--; /* Remove the bang.  */
     242             : 
     243         419 :       if (hexlength == 8
     244         183 :           || (!hexprefix && hexlength == 9 && *s == '0'))
     245             :         {
     246             :           /* Short keyid.  */
     247         236 :           if (hexlength == 9)
     248           0 :             s++;
     249         236 :           desc->u.kid[1] = strtoul( s, NULL, 16 );
     250         236 :           mode = KEYDB_SEARCH_MODE_SHORT_KID;
     251             :         }
     252         183 :       else if (hexlength == 16
     253         151 :                || (!hexprefix && hexlength == 17 && *s == '0'))
     254          32 :         {
     255             :           /* Long keyid.  */
     256             :           char buf[9];
     257          32 :           if (hexlength == 17)
     258           0 :             s++;
     259          32 :           mem2str (buf, s, 9);
     260          32 :           desc->u.kid[0] = strtoul (buf, NULL, 16);
     261          32 :           desc->u.kid[1] = strtoul (s+8, NULL, 16);
     262          32 :           mode = KEYDB_SEARCH_MODE_LONG_KID;
     263             :         }
     264         151 :       else if (hexlength == 32
     265         151 :                || (!hexprefix && hexlength == 33 && *s == '0'))
     266           0 :         {
     267             :           /* MD5 fingerprint.  */
     268             :           int i;
     269           0 :           if (hexlength == 33)
     270           0 :             s++;
     271           0 :           memset (desc->u.fpr+16, 0, 4);
     272           0 :           for (i=0; i < 16; i++, s+=2)
     273             :             {
     274           0 :               int c = hextobyte(s);
     275           0 :               if (c == -1)
     276           0 :                 return gpg_error (GPG_ERR_INV_USER_ID);
     277           0 :               desc->u.fpr[i] = c;
     278             :             }
     279           0 :           mode = KEYDB_SEARCH_MODE_FPR16;
     280             :         }
     281         151 :       else if (hexlength == 40
     282         148 :                || (!hexprefix && hexlength == 41 && *s == '0'))
     283           3 :         {
     284             :           /* SHA1/RMD160 fingerprint.  */
     285             :           int i;
     286           3 :           if (hexlength == 41)
     287           0 :             s++;
     288          63 :           for (i=0; i < 20; i++, s+=2)
     289             :             {
     290          60 :               int c = hextobyte(s);
     291          60 :               if (c == -1)
     292           0 :                 return gpg_error (GPG_ERR_INV_USER_ID);
     293          60 :               desc->u.fpr[i] = c;
     294             :             }
     295           3 :           mode = KEYDB_SEARCH_MODE_FPR20;
     296             :         }
     297         148 :       else if (!hexprefix)
     298             :         {
     299             :           /* The fingerprint in an X.509 listing is often delimited by
     300             :              colons, so we try to single this case out. */
     301         148 :           mode = 0;
     302         148 :           hexlength = strspn (s, ":0123456789abcdefABCDEF");
     303         148 :           if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
     304             :             {
     305             :               int i;
     306             : 
     307           0 :               for (i=0; i < 20; i++, s += 3)
     308             :                 {
     309           0 :                   int c = hextobyte(s);
     310           0 :                   if (c == -1 || (i < 19 && s[2] != ':'))
     311             :                     break;
     312           0 :                   desc->u.fpr[i] = c;
     313             :                 }
     314           0 :               if (i == 20)
     315           0 :                 mode = KEYDB_SEARCH_MODE_FPR20;
     316             :             }
     317         148 :           if (!mode)
     318             :             {
     319             :               /* Still not found.  Now check for a space separated
     320             :                  OpenPGP v4 fingerprint like:
     321             :                    8061 5870 F5BA D690 3336  86D0 F2AD 85AC 1E42 B367
     322             :                  or
     323             :                    8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
     324             :                */
     325         148 :               hexlength = strspn (s, " 0123456789abcdefABCDEF");
     326         148 :               if (s[hexlength] && s[hexlength] != ' ')
     327         146 :                 hexlength = 0; /* Followed by non-space.  */
     328         296 :               while (hexlength && s[hexlength-1] == ' ')
     329           0 :                 hexlength--;   /* Trim trailing spaces.  */
     330         148 :               if ((hexlength == 49 || hexlength == 50)
     331           2 :                   && (!s[hexlength] || s[hexlength] == ' '))
     332             :                 {
     333             :                   int i, c;
     334             : 
     335          42 :                   for (i=0; i < 20; i++)
     336             :                     {
     337          40 :                       if (i && !(i % 2))
     338             :                         {
     339          18 :                           if (*s != ' ')
     340           0 :                             break;
     341          18 :                           s++;
     342             :                           /* Skip the double space in the middle but
     343             :                              don't require it to help copying
     344             :                              fingerprints from sources which fold
     345             :                              multiple space to one.  */
     346          18 :                           if (i == 10 && *s == ' ')
     347           2 :                             s++;
     348             :                         }
     349             : 
     350          40 :                       c = hextobyte(s);
     351          40 :                       if (c == -1)
     352           0 :                         break;
     353          40 :                       desc->u.fpr[i] = c;
     354          40 :                       s += 2;
     355             :                     }
     356           2 :                   if (i == 20)
     357           2 :                     mode = KEYDB_SEARCH_MODE_FPR20;
     358             :                 }
     359             :             }
     360         148 :           if (!mode) /* Default to substring search.  */
     361             :             {
     362         146 :               desc->exact = 0;
     363         146 :               desc->u.name = s;
     364         146 :               mode = KEYDB_SEARCH_MODE_SUBSTR;
     365             :             }
     366             :         }
     367             :       else
     368             :         {
     369             :           /* Hex number with a prefix but with a wrong length.  */
     370           0 :           return gpg_error (GPG_ERR_INV_USER_ID);
     371             :         }
     372             :     }
     373             : 
     374         419 :   desc->mode = mode;
     375         419 :   return 0;
     376             : }

Generated by: LCOV version 1.11