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