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
6 * This file is part of GnuPG.
8 * This file is free software; you can redistribute it and/or modify
9 * it under the terms of either
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.
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.
21 * or both in parallel, as here.
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.
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/>.
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.
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
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
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.
71 classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
79 KEYDB_SEARCH_DESC dummy_desc;
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
87 memset (desc, 0, sizeof *desc);
89 /* Skip leading and trailing spaces. */
90 for(s = name; *s && spacep (s); s++ )
92 if (*s && spacep (s + strlen(s) - 1))
97 rc = gpg_error_from_syserror ();
100 trim_trailing_spaces (s2);
106 case 0: /* Empty string is an error. */
107 rc = gpg_error (GPG_ERR_INV_USER_ID);
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;
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. */
128 case '@': /* Part of an email address. */
129 mode = KEYDB_SEARCH_MODE_MAILSUB;
134 case '=': /* Exact compare. */
135 mode = KEYDB_SEARCH_MODE_EXACT;
140 case '*': /* Case insensitive substring search. */
141 mode = KEYDB_SEARCH_MODE_SUBSTR;
146 case '+': /* Compare individual words. Note that this has not
147 yet been implemented in the search code. */
148 mode = KEYDB_SEARCH_MODE_WORDS;
153 case '/': /* Subject's DN. */
155 if (!*s || spacep (s)) /* No DN or prefixed with a space. */
157 rc = gpg_error (GPG_ERR_INV_USER_ID);
161 mode = KEYDB_SEARCH_MODE_SUBJECT;
164 case '#': /* S/N with optional issuer id or just issuer id. */
170 { /* "#/" indicates an issuer's DN. */
172 if (!*s || spacep (s)) /* No DN or prefixed with a space. */
174 rc = gpg_error (GPG_ERR_INV_USER_ID);
178 mode = KEYDB_SEARCH_MODE_ISSUER;
181 { /* Serialnumber + optional issuer ID. */
182 for (si=s; *si && *si != '/'; si++)
184 /* Check for an invalid digit in the serial number. */
185 if (!strchr("01234567890abcdefABCDEF", *si))
187 rc = gpg_error (GPG_ERR_INV_USER_ID);
191 desc->sn = (const unsigned char*)s;
194 mode = KEYDB_SEARCH_MODE_SN;
198 if (!*s || spacep (s)) /* No DN or prefixed with a space. */
200 rc = gpg_error (GPG_ERR_INV_USER_ID);
204 mode = KEYDB_SEARCH_MODE_ISSUER_SN;
210 case ':': /* Unified fingerprint. */
215 se = strchr (++s,':');
218 rc = gpg_error (GPG_ERR_INV_USER_ID);
221 for (i=0,si=s; si < se; si++, i++ )
223 if (!strchr("01234567890abcdefABCDEF", *si))
225 rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid digit. */
229 if (i != 32 && i != 40)
231 rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr. */
234 for (i=0,si=s; si < se; i++, si +=2)
235 desc->u.fpr[i] = hextobyte(si);
238 mode = KEYDB_SEARCH_MODE_FPR;
242 case '&': /* Keygrip*/
244 if (hex2bin (s+1, desc->u.grip, 20) < 0)
246 rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid. */
249 mode = KEYDB_SEARCH_MODE_KEYGRIP;
254 if (s[0] == '0' && s[1] == 'x')
260 hexlength = strspn(s, "0123456789abcdefABCDEF");
261 if (hexlength >= 8 && s[hexlength] =='!')
264 hexlength++; /* Just for the following check. */
267 /* Check if a hexadecimal number is terminated by EOS or blank. */
268 if (hexlength && s[hexlength] && !spacep (s+hexlength))
270 if (hexprefix) /* A "0x" prefix without a correct
271 termination is an error. */
273 rc = gpg_error (GPG_ERR_INV_USER_ID);
276 /* The first characters looked like a hex number, but the
277 entire string is not. */
282 hexlength--; /* Remove the bang. */
285 && (s[hexlength] == 0
286 || (s[hexlength] == '!' && s[hexlength + 1] == 0)))
287 || (!hexprefix && hexlength == 9 && *s == '0'))
292 desc->u.kid[1] = strtoul( s, NULL, 16 );
293 mode = KEYDB_SEARCH_MODE_SHORT_KID;
295 else if ((hexlength == 16
296 && (s[hexlength] == 0
297 || (s[hexlength] == '!' && s[hexlength + 1] == 0)))
298 || (!hexprefix && hexlength == 17 && *s == '0'))
305 desc->u.kid[0] = strtoul (buf, NULL, 16);
306 desc->u.kid[1] = strtoul (s+8, NULL, 16);
307 mode = KEYDB_SEARCH_MODE_LONG_KID;
309 else if ((hexlength == 32
310 && (s[hexlength] == 0
311 || (s[hexlength] == '!' && s[hexlength + 1] == 0)))
312 || (!hexprefix && hexlength == 33 && *s == '0'))
314 /* MD5 fingerprint. */
318 memset (desc->u.fpr+16, 0, 4);
319 for (i=0; i < 16; i++, s+=2)
321 int c = hextobyte(s);
324 rc = gpg_error (GPG_ERR_INV_USER_ID);
329 mode = KEYDB_SEARCH_MODE_FPR16;
331 else if ((hexlength == 40
332 && (s[hexlength] == 0
333 || (s[hexlength] == '!' && s[hexlength + 1] == 0)))
334 || (!hexprefix && hexlength == 41 && *s == '0'))
336 /* SHA1/RMD160 fingerprint. */
340 for (i=0; i < 20; i++, s+=2)
342 int c = hextobyte(s);
345 rc = gpg_error (GPG_ERR_INV_USER_ID);
350 mode = KEYDB_SEARCH_MODE_FPR20;
354 /* The fingerprint in an X.509 listing is often delimited by
355 colons, so we try to single this case out. */
357 hexlength = strspn (s, ":0123456789abcdefABCDEF");
358 if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
362 for (i=0; i < 20; i++, s += 3)
364 int c = hextobyte(s);
365 if (c == -1 || (i < 19 && s[2] != ':'))
370 mode = KEYDB_SEARCH_MODE_FPR20;
374 /* Still not found. Now check for a space separated
375 OpenPGP v4 fingerprint like:
376 8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
378 8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
380 hexlength = strspn (s, " 0123456789abcdefABCDEF");
381 if (s[hexlength] && s[hexlength] != ' ')
382 hexlength = 0; /* Followed by non-space. */
383 while (hexlength && s[hexlength-1] == ' ')
384 hexlength--; /* Trim trailing spaces. */
385 if ((hexlength == 49 || hexlength == 50)
386 && (!s[hexlength] || s[hexlength] == ' '))
390 for (i=0; i < 20; i++)
397 /* Skip the double space in the middle but
398 don't require it to help copying
399 fingerprints from sources which fold
400 multiple space to one. */
401 if (i == 10 && *s == ' ')
412 mode = KEYDB_SEARCH_MODE_FPR20;
415 if (!mode) /* Default to substring search. */
419 mode = KEYDB_SEARCH_MODE_SUBSTR;
424 /* Hex number with a prefix but with a wrong length. */
425 rc = gpg_error (GPG_ERR_INV_USER_ID);