From 9a96043be4bed4e18320918e042b1601c9d93e95 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 8 Dec 2009 16:30:33 +0000 Subject: [PATCH] Unification of the search descriptor usage. --- NEWS | 2 +- agent/ChangeLog | 4 + agent/protect.c | 1 + common/ChangeLog | 5 +- common/Makefile.am | 1 + common/dns-cert.c | 2 +- common/userids.c | 322 +++++++++++++++++++++++++++++++++++++++ common/userids.h | 28 ++++ g10/ChangeLog | 20 +++ g10/delkey.c | 7 +- g10/export.c | 5 +- g10/getkey.c | 230 +--------------------------- g10/gpg.h | 3 - g10/keydb.h | 30 ---- g10/keyring.h | 1 + g10/keyserver.c | 41 ++--- g10/packet.h | 18 ++- g10/pkclist.c | 2 +- g10/revoke.c | 10 +- g10/trustdb.c | 4 +- kbx/ChangeLog | 8 + kbx/keybox-search-desc.h | 15 +- kbx/keybox-search.c | 28 +++- sm/ChangeLog | 9 ++ sm/certlist.c | 4 +- sm/delete.c | 2 +- sm/export.c | 4 +- sm/import.c | 2 +- sm/keydb.c | 284 +--------------------------------- sm/keydb.h | 4 +- sm/keylist.c | 2 +- sm/sign.c | 2 +- 32 files changed, 501 insertions(+), 599 deletions(-) create mode 100644 common/userids.c create mode 100644 common/userids.h diff --git a/NEWS b/NEWS index 0d543cdaf..53c4a88ef 100644 --- a/NEWS +++ b/NEWS @@ -14,7 +14,7 @@ Noteworthy changes in version 2.1.x (under development) * Numerical values may now be used as an alternative to the debug-level keywords. - * Support SRV and PKA records on W32. + * Support DNS lookups for SRV, PKA and CERT on W32. Noteworthy changes in version 2.0.13 (2009-09-04) diff --git a/agent/ChangeLog b/agent/ChangeLog index 5618f06d6..ceb693f5b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2009-12-08 Werner Koch + + * protect.c (agent_unprotect): Avoid compiler warning. + 2009-12-08 Marcus Brinkmann * call-pinentry.c (start_pinentry): Convert posix fd to assuan fd. diff --git a/agent/protect.c b/agent/protect.c index d6457ad2a..54f6bd38a 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -775,6 +775,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase, if (!n) return gpg_error (GPG_ERR_INV_SEXP); + cleartext = NULL; /* Avoid cc warning. */ rc = do_decryption (s, n, passphrase, s2ksalt, s2kcount, iv, 16, diff --git a/common/ChangeLog b/common/ChangeLog index f71e0e354..ab9a59fbc 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,11 +1,14 @@ 2009-12-08 Werner Koch + * userids.h, userids.c: New. + (classify_user_id): Merged from similar fucntions in sm/ and g10/. + * dns-cert.c (get_dns_cert): Add support for ADNS. 2009-12-08 Marcus Brinkmann * asshelp.c (start_new_gpg_agent): Convert posix FD to assuan FD. - + * asshelp.c (start_new_gpg_agent) [HAVE_W32_SYSTEM]: Add missing argument in assuan_socket_connect invocation. * iobuf.c (iobuf_open_fd_or_name): Fix type of FD in function diff --git a/common/Makefile.am b/common/Makefile.am index 29312c9dc..d5446ddd2 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -70,6 +70,7 @@ common_sources = \ http.c http.h \ localename.c \ session-env.c session-env.h \ + userids.c userids.h \ helpfile.c # Sources only useful without PTH. diff --git a/common/dns-cert.c b/common/dns-cert.c index 54441d308..efdefaf16 100644 --- a/common/dns-cert.c +++ b/common/dns-cert.c @@ -1,5 +1,5 @@ /* dns-cert.c - DNS CERT code - * Copyright (C) 2005, 2006 Free Software Foundation, Inc. + * Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc. * * This file is part of GNUPG. * diff --git a/common/userids.c b/common/userids.c new file mode 100644 index 000000000..9a072dd80 --- /dev/null +++ b/common/userids.c @@ -0,0 +1,322 @@ +/* userids.c - Utility functions for user ids. + * Copyright (C) 2001, 2003, 2004, 2006, + * 2009 Free Software Foundation, Inc. + * + * 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. + * + * GnuPG 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* 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 +#include +#include +#include + +#include "util.h" +#include "userids.h" + + +/* 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 + * check the validity of a user-id. + * + * Some used rules: + * - If the username starts with 8,9,16 or 17 hex-digits (the first one + * must be in the range 0..9), this is considered a keyid; depending + * on the length a short or complete one. + * - If the username starts with 32,33,40 or 41 hex-digits (the first one + * 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 '.', 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 + * email address + * - If the userid start with an '=' an exact compare is done. + * - If the userid starts with a '*' a case insensitive substring search is + * done (This is the default). + * - If the userid starts with a '+' we will compare individual words + * and a match requires that all the words are in the userid. + * Words are delimited by white space or "()<>[]{}.@-+_,;/&!" + * (note that you can't search for these characters). Compare + * is not case sensitive. + * - If the userid starts with a '&' a 40 hex digits keygrip is expected. + */ + +gpg_error_t +classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc) +{ + const char *s; + int hexprefix = 0; + int hexlength; + 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. */ + memset (desc, 0, sizeof *desc); + + /* Skip leading spaces. */ + for(s = name; *s && spacep (s); s++ ) + ; + + switch (*s) + { + case 0: /* Empty string is an error. */ + return gpg_error (GPG_ERR_INV_USER_ID); + + case '.': /* An email address, compare from end. Note that this + has not yet been implemented in the search code. */ + mode = KEYDB_SEARCH_MODE_MAILEND; + s++; + desc->u.name = s; + break; + + case '<': /* An email address. */ + mode = KEYDB_SEARCH_MODE_MAIL; + s++; + desc->u.name = s; + break; + + case '@': /* Part of an email address. */ + mode = KEYDB_SEARCH_MODE_MAILSUB; + s++; + desc->u.name = s; + break; + + case '=': /* Exact compare. */ + mode = KEYDB_SEARCH_MODE_EXACT; + s++; + desc->u.name = s; + break; + + case '*': /* Case insensitive substring search. */ + mode = KEYDB_SEARCH_MODE_SUBSTR; + s++; + desc->u.name = s; + break; + + case '+': /* Compare individual words. Note that this has not + yet been implemented in the search code. */ + mode = KEYDB_SEARCH_MODE_WORDS; + s++; + desc->u.name = s; + break; + + case '/': /* Subject's DN. */ + s++; + if (!*s || spacep (s)) /* No DN or prefixed with a space. */ + return gpg_error (GPG_ERR_INV_USER_ID); + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_SUBJECT; + 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); + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_ISSUER; + } + else + { /* Serialnumber + optional issuer ID. */ + for (si=s; *si && *si != '/'; si++) + { + /* Check for an invalid digit in the serial number. */ + if (!strchr("01234567890abcdefABCDEF", *si)) + return gpg_error (GPG_ERR_INV_USER_ID); + } + desc->sn = (const unsigned char*)s; + desc->snlen = -1; + if (!*si) + mode = KEYDB_SEARCH_MODE_SN; + else + { + s = si+1; + if (!*s || spacep (s)) /* No DN or prefixed with a space. */ + return gpg_error (GPG_ERR_INV_USER_ID); + desc->u.name = s; + mode = KEYDB_SEARCH_MODE_ISSUER_SN; + } + } + } + break; + + case ':': /* Unified fingerprint. */ + { + const char *se, *si; + int i; + + se = strchr (++s,':'); + if (!se) + return gpg_error (GPG_ERR_INV_USER_ID); + for (i=0,si=s; si < se; si++, i++ ) + { + if (!strchr("01234567890abcdefABCDEF", *si)) + return gpg_error (GPG_ERR_INV_USER_ID); /* Invalid digit. */ + } + 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) + 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: + if (s[0] == '0' && s[1] == 'x') + { + hexprefix = 1; + s += 2; + } + + hexlength = strspn(s, "0123456789abcdefABCDEF"); + if (hexlength >= 8 && s[hexlength] =='!') + { + 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 (hexprefix) /* A "0x" prefix without a correct + termination is an error. */ + return gpg_error (GPG_ERR_INV_USER_ID); + /* The first characters looked like a hex number, but the + entire string is not. */ + hexlength = 0; + } + + if (desc->exact) + hexlength--; /* Remove the bang. */ + + if (hexlength == 8 + || (!hexprefix && hexlength == 9 && *s == '0')) + { + /* Short keyid. */ + if (hexlength == 9) + 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) + s++; + mem2str (buf, s, 9); + desc->u.kid[0] = strtoul (buf, NULL, 16); + desc->u.kid[1] = strtoul (s+8, NULL, 16); + mode = KEYDB_SEARCH_MODE_LONG_KID; + } + 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) + { + int c = hextobyte(s); + if (c == -1) + return gpg_error (GPG_ERR_INV_USER_ID); + desc->u.fpr[i] = c; + } + mode = KEYDB_SEARCH_MODE_FPR16; + } + 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) + { + int c = hextobyte(s); + if (c == -1) + return gpg_error (GPG_ERR_INV_USER_ID); + desc->u.fpr[i] = c; + } + 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))) + { + int i; + + for (i=0; i < 20; i++, s += 3) + { + int c = hextobyte(s); + if (c == -1 || (i < 19 && s[2] != ':')) + break; + desc->u.fpr[i] = c; + } + 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; + } + } + else + { + /* Hex number with a prefix but with a wrong length. */ + return gpg_error (GPG_ERR_INV_USER_ID); + } + } + + desc->mode = mode; + return 0; +} diff --git a/common/userids.h b/common/userids.h new file mode 100644 index 000000000..246b10768 --- /dev/null +++ b/common/userids.h @@ -0,0 +1,28 @@ +/* userids.h - Utility functions for user ids. + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * 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. + * + * GnuPG 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef GNUPG_COMMON_USERIDS_H +#define GNUPG_COMMON_USERIDS_H + +#include "../kbx/keybox-search-desc.h" + +gpg_error_t classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc); + + +#endif /*GNUPG_COMMON_USERIDS_H*/ diff --git a/g10/ChangeLog b/g10/ChangeLog index 9ac9f8589..873167c17 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,23 @@ +2009-12-08 Werner Koch + + * keyring.h: Include userids.h. + * gpg.h (KEYDB_SEARCH_DESC): Remove. + * packet.h: Include userids.h. + (PKT_user_id): Declare using gpg_pkt_user_id_s. + * keydb.h (KeydbSearchMode, struct keydb_search_desc): Remove. We + now use those in ../kbx. + * getkey.c (classify_user_id): Remove. It is now in common/. + (key_byname): Adjust for changed classify_user_id. + * delkey.c (do_delete_key): Ditto. + * trustdb.c (register_trusted_key): Ditto. + * revoke.c (gen_desig_revoke, gen_revoke): Ditto. + * keyserver.c (parse_keyrec, keyserver_export, keyserver_import) + (keyidlist): Ditto. + * export.c (do_export_stream): Ditto. + + * pkclist.c (find_and_check_key): Replace GPG_ERR_INV_NAME by + GPG_ERR_INV_USER_ID. + 2009-12-04 Werner Koch * keygen.c (DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE): New. diff --git a/g10/delkey.c b/g10/delkey.c index fe29d52ea..5d86e7291 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -63,12 +63,13 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail ) *r_sec_avail = 0; - /* search the userid */ - classify_user_id (username, &desc); + /* Search the userid */ + rc = classify_user_id (username, &desc); exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR || desc.mode == KEYDB_SEARCH_MODE_FPR16 || desc.mode == KEYDB_SEARCH_MODE_FPR20); - rc = desc.mode? keydb_search (hd, &desc, 1):G10ERR_INV_USER_ID; + if (!rc) + rc = keydb_search (hd, &desc, 1); if (rc) { log_error (_("key \"%s\" not found: %s\n"), username, g10_errstr (rc)); write_status_text( STATUS_DELETE_PROBLEM, "1" ); diff --git a/g10/export.c b/g10/export.c index 9b87e5924..3a4c665c9 100644 --- a/g10/export.c +++ b/g10/export.c @@ -293,6 +293,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret, KBNODE *keyblock_out, unsigned int options, int *any ) { int rc = 0; + gpg_error_t err; PACKET pkt; KBNODE keyblock = NULL; KBNODE kbctx, node; @@ -318,11 +319,11 @@ do_export_stream( IOBUF out, strlist_t users, int secret, desc = xmalloc ( ndesc * sizeof *desc); for (ndesc=0, sl=users; sl; sl = sl->next) { - if (classify_user_id (sl->d, desc+ndesc)) + if (!(err=classify_user_id (sl->d, desc+ndesc))) ndesc++; else log_error (_("key \"%s\" not found: %s\n"), - sl->d, g10_errstr (G10ERR_INV_USER_ID)); + sl->d, gpg_strerror (err)); } /* It would be nice to see which of the given users did diff --git a/g10/getkey.c b/g10/getkey.c index 54843cfb2..c636d6b0e 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -536,228 +536,6 @@ seckey_available( u32 *keyid ) } -/**************** - * Return the type of the user id: - * - * Please use the constants KEYDB_SERCH_MODE_xxx - * 0 = Invalid user ID - * 1 = exact match - * 2 = match a substring - * 3 = match an email address - * 4 = match a substring of an email address - * 5 = match an email address, but compare from end - * 6 = word match mode - * 10 = it is a short KEYID (don't care about keyid[0]) - * 11 = it is a long KEYID - * 12 = it is a trustdb index (keyid is looked up) - * 16 = it is a 16 byte fingerprint - * 20 = it is a 20 byte fingerprint - * 21 = Unified fingerprint :fpr:pk_algo: - * (We don't use pk_algo yet) - * - * Rules used: - * - If the username starts with 8,9,16 or 17 hex-digits (the first one - * must be in the range 0..9), this is considered a keyid; depending - * on the length a short or complete one. - * - If the username starts with 32,33,40 or 41 hex-digits (the first one - * 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 '.', 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 - * email address - * - If the userid start with an '=' an exact compare is done. - * - If the userid starts with a '*' a case insensitive substring search is - * done (This is the default). - * - If the userid starts with a '+' we will compare individual words - * and a match requires that all the words are in the userid. - * Words are delimited by white space or "()<>[]{}.@-+_,;/&!" - * (note that you can't search for these characters). Compare - * is not case sensitive. - * - If the userid starts with a '&' a 40 hex digits keygrip is expected. - */ - -int -classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc ) -{ - const char *s; - int hexprefix = 0; - int hexlength; - 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 */ - memset (desc, 0, sizeof *desc); - - /* skip leading spaces. Fixme: what is with trailing spaces? */ - for(s = name; *s && spacep (s); s++ ) - ; - - switch (*s) { - case 0: /* empty string is an error */ - return 0; - -#if 0 - case '.': /* an email address, compare from end */ - mode = KEYDB_SEARCH_MODE_MAILEND; - s++; - desc->u.name = s; - break; -#endif - - case '<': /* an email address */ - mode = KEYDB_SEARCH_MODE_MAIL; - desc->u.name = s; - break; - - case '@': /* part of an email address */ - mode = KEYDB_SEARCH_MODE_MAILSUB; - s++; - desc->u.name = s; - break; - - case '=': /* exact compare */ - mode = KEYDB_SEARCH_MODE_EXACT; - s++; - desc->u.name = s; - break; - - case '*': /* case insensitive substring search */ - mode = KEYDB_SEARCH_MODE_SUBSTR; - s++; - desc->u.name = s; - break; - -#if 0 - case '+': /* compare individual words */ - mode = KEYDB_SEARCH_MODE_WORDS; - s++; - desc->u.name = s; - break; -#endif - - case '#': /* local user id */ - return 0; /* This is now obsolete and can't not be used anymore*/ - - case ':': /*Unified fingerprint */ - { - const char *se, *si; - int i; - - se = strchr( ++s,':'); - if ( !se ) - return 0; - for (i=0,si=s; si < se; si++, i++ ) { - if ( !strchr("01234567890abcdefABCDEF", *si ) ) - return 0; /* invalid digit */ - } - if (i != 32 && i != 40) - return 0; /* invalid length of fpr*/ - 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 */ - return 0; /* Not yet implememted. */ - - default: - if (s[0] == '0' && s[1] == 'x') { - hexprefix = 1; - s += 2; - } - - hexlength = strspn(s, "0123456789abcdefABCDEF"); - if (hexlength >= 8 && s[hexlength] =='!') { - 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 (hexprefix) /* a "0x" prefix without correct */ - return 0; /* termination is an error */ - else /* The first chars looked like */ - hexlength = 0; /* a hex number, but really were not. */ - } - - if (desc->exact) - hexlength--; - - if (hexlength == 8 - || (!hexprefix && hexlength == 9 && *s == '0')){ - /* short keyid */ - if (hexlength == 9) - s++; - desc->u.kid[0] = 0; - desc->u.kid[1] = strtoul( s, NULL, 16 ); - mode = KEYDB_SEARCH_MODE_SHORT_KID; - } - else if (hexlength == 16 - || (!hexprefix && hexlength == 17 && *s == '0')) { - /* complete keyid */ - char buf[9]; - if (hexlength == 17) - s++; - mem2str(buf, s, 9 ); - desc->u.kid[0] = strtoul( buf, NULL, 16 ); - desc->u.kid[1] = strtoul( s+8, NULL, 16 ); - mode = KEYDB_SEARCH_MODE_LONG_KID; - } - 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) { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR16; - } - 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) { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR20; - } - else { - if (hexprefix) /* This was a hex number with a prefix */ - return 0; /* and a wrong length */ - - desc->exact = 0; - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBSTR; /* default mode */ - } - } - - desc->mode = mode; - return mode; -} - static int skip_unusable (void *dummy, u32 *keyid, PKT_user_id *uid) @@ -851,14 +629,16 @@ key_byname( GETKEY_CTX *retctx, strlist_t namelist, for(n=0, r=namelist; r; r = r->next, n++ ) { - classify_user_id (r->d, &ctx->items[n]); + gpg_error_t err; + + err = classify_user_id (r->d, &ctx->items[n]); if (ctx->items[n].exact) ctx->exact = 1; - if (!ctx->items[n].mode) + if (err) { xfree (ctx); - return G10ERR_INV_USER_ID; + return gpg_err_code (err); /* FIXME: remove gpg_err_code. */ } if(!include_unusable && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID diff --git a/g10/gpg.h b/g10/gpg.h index b53303e13..da2a738dc 100644 --- a/g10/gpg.h +++ b/g10/gpg.h @@ -50,9 +50,6 @@ struct server_local_s; /* Object used to describe a keyblok node. */ typedef struct kbnode_struct *KBNODE; -/* Object used for looking ob keys. */ -typedef struct keydb_search_desc KEYDB_SEARCH_DESC; - /* Session control object. This object is passed to most functions to diff --git a/g10/keydb.h b/g10/keydb.h index c58a1012b..68949a7f9 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -115,35 +115,6 @@ struct pubkey_find_info { typedef struct keydb_handle *KEYDB_HANDLE; -typedef enum { - KEYDB_SEARCH_MODE_NONE, - KEYDB_SEARCH_MODE_EXACT, - KEYDB_SEARCH_MODE_SUBSTR, - KEYDB_SEARCH_MODE_MAIL, - KEYDB_SEARCH_MODE_MAILSUB, - KEYDB_SEARCH_MODE_MAILEND, - KEYDB_SEARCH_MODE_WORDS, - KEYDB_SEARCH_MODE_SHORT_KID, - KEYDB_SEARCH_MODE_LONG_KID, - KEYDB_SEARCH_MODE_FPR16, - KEYDB_SEARCH_MODE_FPR20, - KEYDB_SEARCH_MODE_FPR, - KEYDB_SEARCH_MODE_FIRST, - KEYDB_SEARCH_MODE_NEXT -} KeydbSearchMode; - -struct keydb_search_desc { - KeydbSearchMode mode; - int (*skipfnc)(void *,u32*,PKT_user_id*); - void *skipfncvalue; - union { - const char *name; - byte fpr[MAX_FINGERPRINT_LEN]; - u32 kid[2]; - } u; - int exact; -}; - /* Helper type for preference fucntions. */ union pref_hint @@ -221,7 +192,6 @@ char *get_last_passphrase(void); void next_to_last_passphrase(void); /*-- getkey.c --*/ -int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc); void cache_public_key( PKT_public_key *pk ); void getkey_disable_caches(void); int get_pubkey( PKT_public_key *pk, u32 *keyid ); diff --git a/g10/keyring.h b/g10/keyring.h index 928605cd1..420e1792e 100644 --- a/g10/keyring.h +++ b/g10/keyring.h @@ -20,6 +20,7 @@ #ifndef GPG_KEYRING_H #define GPG_KEYRING_H 1 +#include "../common/userids.h" typedef struct keyring_handle *KEYRING_HANDLE; diff --git a/g10/keyserver.c b/g10/keyserver.c index 36c52f0a7..461444f1c 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -46,6 +46,7 @@ #include "srv.h" #endif + #ifdef HAVE_W32_SYSTEM /* It seems Vista doesn't grok X_OK and so fails access() tests. Previous versions interpreted X_OK as F_OK anyway, so we'll just @@ -595,6 +596,7 @@ parse_keyrec(char *keystring) if(ascii_strcasecmp("pub",record)==0) { char *tok; + gpg_error_t err; if(work->desc.mode) { @@ -606,11 +608,11 @@ parse_keyrec(char *keystring) if((tok=strsep(&keystring,":"))==NULL) return ret; - classify_user_id(tok,&work->desc); - if(work->desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID - && work->desc.mode!=KEYDB_SEARCH_MODE_LONG_KID - && work->desc.mode!=KEYDB_SEARCH_MODE_FPR16 - && work->desc.mode!=KEYDB_SEARCH_MODE_FPR20) + err = classify_user_id (tok, &work->desc); + if (err || (work->desc.mode != KEYDB_SEARCH_MODE_SHORT_KID + && work->desc.mode != KEYDB_SEARCH_MODE_LONG_KID + && work->desc.mode != KEYDB_SEARCH_MODE_FPR16 + && work->desc.mode != KEYDB_SEARCH_MODE_FPR20)) { work->desc.mode=KEYDB_SEARCH_MODE_NONE; return ret; @@ -1598,6 +1600,7 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc, int keyserver_export(strlist_t users) { + gpg_error_t err; strlist_t sl=NULL; KEYDB_SEARCH_DESC desc; int rc=0; @@ -1605,11 +1608,11 @@ keyserver_export(strlist_t users) /* Weed out descriptors that we don't support sending */ for(;users;users=users->next) { - classify_user_id (users->d, &desc); - if(desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID && - desc.mode!=KEYDB_SEARCH_MODE_LONG_KID && - desc.mode!=KEYDB_SEARCH_MODE_FPR16 && - desc.mode!=KEYDB_SEARCH_MODE_FPR20) + err = classify_user_id (users->d, &desc); + if (err || (desc.mode != KEYDB_SEARCH_MODE_SHORT_KID + && desc.mode != KEYDB_SEARCH_MODE_LONG_KID + && desc.mode != KEYDB_SEARCH_MODE_FPR16 + && desc.mode != KEYDB_SEARCH_MODE_FPR20)) { log_error(_("\"%s\" not a key ID: skipping\n"),users->d); continue; @@ -1630,6 +1633,7 @@ keyserver_export(strlist_t users) int keyserver_import(strlist_t users) { + gpg_error_t err; KEYDB_SEARCH_DESC *desc; int num=100,count=0; int rc=0; @@ -1639,13 +1643,13 @@ keyserver_import(strlist_t users) for(;users;users=users->next) { - classify_user_id (users->d, &desc[count]); - if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID && - desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID && - desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 && - desc[count].mode!=KEYDB_SEARCH_MODE_FPR20) + err = classify_user_id (users->d, &desc[count]); + if (err || (desc[count].mode != KEYDB_SEARCH_MODE_SHORT_KID + && desc[count].mode != KEYDB_SEARCH_MODE_LONG_KID + && desc[count].mode != KEYDB_SEARCH_MODE_FPR16 + && desc[count].mode != KEYDB_SEARCH_MODE_FPR20)) { - log_error(_("\"%s\" not a key ID: skipping\n"),users->d); + log_error (_("\"%s\" not a key ID: skipping\n"), users->d); continue; } @@ -1731,11 +1735,12 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) for (ndesc=0, sl=users; sl; sl = sl->next) { - if(classify_user_id (sl->d, desc+ndesc)) + gpg_error_t err; + if (!(err = classify_user_id (sl->d, desc+ndesc))) ndesc++; else log_error (_("key \"%s\" not found: %s\n"), - sl->d, g10_errstr (G10ERR_INV_USER_ID)); + sl->d, gpg_strerror (err)); } } diff --git a/g10/packet.h b/g10/packet.h index 395e70ab9..2ceaba4f3 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -27,6 +27,7 @@ #include "cipher.h" #include "filter.h" #include "../common/openpgpdefs.h" +#include "../common/userids.h" #define DEBUG_PARSE_PACKET 1 @@ -151,14 +152,16 @@ typedef struct #define ATTRIB_IMAGE 1 -/* This is the cooked form of attributes */ +/* This is the cooked form of attributes. */ struct user_attribute { byte type; const byte *data; u32 len; }; -typedef struct + +/* (See also keybox-search-desc.h) */ +struct gpg_pkt_user_id_s { int ref; /* reference counter */ int len; /* length of the name */ @@ -181,12 +184,15 @@ typedef struct struct { /* TODO: Move more flags here */ - unsigned mdc:1; - unsigned ks_modify:1; - unsigned compacted:1; + unsigned int mdc:1; + unsigned int ks_modify:1; + unsigned int compacted:1; } flags; char name[1]; -} PKT_user_id; +}; +typedef struct gpg_pkt_user_id_s PKT_user_id; + + struct revoke_info { diff --git a/g10/pkclist.c b/g10/pkclist.c index 16835926e..cbc76c76d 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -787,7 +787,7 @@ find_and_check_key (const char *name, unsigned int use, int trustlevel; if (!name || !*name) - return gpg_error (GPG_ERR_INV_NAME); + return gpg_error (GPG_ERR_INV_USER_ID); pk = xtrycalloc (1, sizeof *pk); if (!pk) diff --git a/g10/revoke.c b/g10/revoke.c index b34684ecd..38b955625 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -220,8 +220,9 @@ gen_desig_revoke( const char *uname, strlist_t locusr ) afx = new_armor_context (); kdbhd = keydb_new (0); - classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + rc = classify_user_id (uname, &desc); + if (!rc) + rc = keydb_search (kdbhd, &desc, 1); if (rc) { log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc)); goto leave; @@ -463,8 +464,9 @@ gen_revoke( const char *uname ) * We don't want the whole getkey stuff here but the entire keyblock */ kdbhd = keydb_new (1); - classify_user_id (uname, &desc); - rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; + rc = classify_user_id (uname, &desc); + if (!rc) + rc = keydb_search (kdbhd, &desc, 1); if (rc) { log_error (_("secret key \"%s\" not found: %s\n"), diff --git a/g10/trustdb.c b/g10/trustdb.c index 2db971526..9bfae9e08 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -214,9 +214,11 @@ register_trusted_keyid(u32 *keyid) void register_trusted_key( const char *string ) { + gpg_error_t err; KEYDB_SEARCH_DESC desc; - if (classify_user_id (string, &desc) != KEYDB_SEARCH_MODE_LONG_KID ) + err = classify_user_id (string, &desc); + if (err || desc.mode != KEYDB_SEARCH_MODE_LONG_KID ) { log_error(_("`%s' is not a valid long keyID\n"), string ); return; diff --git a/kbx/ChangeLog b/kbx/ChangeLog index b4f988234..7b5a546c4 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,11 @@ +2009-12-08 Werner Koch + + * keybox-search-desc.h (keydb_search_desc): Use u32 type for + KID. Extend the skip function ptr. + (gpg_pkt_user_id_t): New. + * keybox-search.c (has_short_kid, has_long_kid): Change to use u32 + args for KID. + 2008-12-09 Werner Koch * kbxutil.c (main): Call i18n_init before init_common_subsystems. diff --git a/kbx/keybox-search-desc.h b/kbx/keybox-search-desc.h index 98d813507..e5da155f8 100644 --- a/kbx/keybox-search-desc.h +++ b/kbx/keybox-search-desc.h @@ -48,24 +48,31 @@ typedef enum { KEYDB_SEARCH_MODE_NEXT } KeydbSearchMode; -struct keydb_search_desc { + +/* Forwward declaration. See g10/packet.h. */ +struct gpg_pkt_user_id_s; +typedef struct gpg_pkt_user_id_s *gpg_pkt_user_id_t; + +/* A search descriptor. */ +struct keydb_search_desc +{ KeydbSearchMode mode; - int (*skipfnc)(void *,void*); /* used to be: void*, u32* */ + int (*skipfnc)(void *, u32 *, gpg_pkt_user_id_t); void *skipfncvalue; const unsigned char *sn; int snlen; /* -1 := sn is a hex string */ union { const char *name; unsigned char fpr[24]; - unsigned char kid[8]; + u32 kid[2]; /* Note that this is in native endianess. */ unsigned char grip[20]; } u; + int exact; /* Use exactly this key ('!' suffix in gpg). */ }; struct keydb_search_desc; typedef struct keydb_search_desc KEYDB_SEARCH_DESC; - typedef struct keydb_search_desc KEYBOX_SEARCH_DESC; diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index 1680dd732..be4ca4579 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -530,15 +530,29 @@ blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip) The has_foo functions are used as helpers for search */ static inline int -has_short_kid (KEYBOXBLOB blob, const unsigned char *kid) +has_short_kid (KEYBOXBLOB blob, u32 lkid) { - return blob_cmp_fpr_part (blob, kid+4, 16, 4); + unsigned char buf[4]; + buf[0] = lkid >> 24; + buf[1] = lkid >> 16; + buf[2] = lkid >> 8; + buf[3] = lkid; + return blob_cmp_fpr_part (blob, buf, 16, 4); } static inline int -has_long_kid (KEYBOXBLOB blob, const unsigned char *kid) +has_long_kid (KEYBOXBLOB blob, u32 mkid, u32 lkid) { - return blob_cmp_fpr_part (blob, kid, 12, 8); + unsigned char buf[8]; + buf[0] = mkid >> 24; + buf[1] = mkid >> 16; + buf[2] = mkid >> 8; + buf[3] = mkid; + buf[4] = lkid >> 24; + buf[5] = lkid >> 16; + buf[6] = lkid >> 8; + buf[7] = lkid; + return blob_cmp_fpr_part (blob, buf, 12, 8); } static inline int @@ -877,11 +891,11 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) goto found; break; case KEYDB_SEARCH_MODE_SHORT_KID: - if (has_short_kid (blob, desc[n].u.kid)) + if (has_short_kid (blob, desc[n].u.kid[1])) goto found; break; case KEYDB_SEARCH_MODE_LONG_KID: - if (has_long_kid (blob, desc[n].u.kid)) + if (has_long_kid (blob, desc[n].u.kid[0], desc[n].u.kid[1])) goto found; break; case KEYDB_SEARCH_MODE_FPR: @@ -909,7 +923,7 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) for (n=any_skip?0:ndesc; n < ndesc; n++) { /* if (desc[n].skipfnc */ -/* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */ +/* && desc[n].skipfnc (desc[n].skipfncvalue, aki, NULL)) */ /* break; */ } if (n == ndesc) diff --git a/sm/ChangeLog b/sm/ChangeLog index a96b90327..bb2b4b37f 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,12 @@ +2009-12-08 Werner Koch + + * keydb.c (keydb_search_kid): Fix code even that it is not used. + (classify_user_id): Adjust for change of u.kid type. + (keydb_classify_name): Replace GPG_ERR_INV_NAME by + GPG_ERR_INV_USER_ID. + (keydb_classify_name): Remove. Replace all callers by + classify_user_id. + 2009-12-08 Marcus Brinkmann * call-dirmngr.c (start_dirmngr_ext): Convert posix fd to assuan fd. diff --git a/sm/certlist.c b/sm/certlist.c index 4137437a6..8221e4ac3 100644 --- a/sm/certlist.c +++ b/sm/certlist.c @@ -301,7 +301,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret, KEYDB_HANDLE kh = NULL; ksba_cert_t cert = NULL; - rc = keydb_classify_name (name, &desc); + rc = classify_user_id (name, &desc); if (!rc) { kh = keydb_new (0); @@ -480,7 +480,7 @@ gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert) KEYDB_HANDLE kh = NULL; *r_cert = NULL; - rc = keydb_classify_name (name, &desc); + rc = classify_user_id (name, &desc); if (!rc) { kh = keydb_new (0); diff --git a/sm/delete.c b/sm/delete.c index fd49ebeab..e2835a98b 100644 --- a/sm/delete.c +++ b/sm/delete.c @@ -45,7 +45,7 @@ delete_one (ctrl_t ctrl, const char *username) int duplicates = 0; int is_ephem = 0; - rc = keydb_classify_name (username, &desc); + rc = classify_user_id (username, &desc); if (rc) { log_error (_("certificate `%s' not found: %s\n"), diff --git a/sm/export.c b/sm/export.c index fcf1dccc1..b194d0dd1 100644 --- a/sm/export.c +++ b/sm/export.c @@ -180,7 +180,7 @@ gpgsm_export (ctrl_t ctrl, strlist_t names, FILE *fp, estream_t stream) { for (ndesc=0, sl=names; sl; sl = sl->next) { - rc = keydb_classify_name (sl->d, desc+ndesc); + rc = classify_user_id (sl->d, desc+ndesc); if (rc) { log_error ("key `%s' not found: %s\n", @@ -359,7 +359,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp) goto leave; } - rc = keydb_classify_name (name, desc); + rc = classify_user_id (name, desc); if (rc) { log_error ("key `%s' not found: %s\n", diff --git a/sm/import.c b/sm/import.c index 5a0eded8f..bcc2d6d44 100644 --- a/sm/import.c +++ b/sm/import.c @@ -452,7 +452,7 @@ reimport_one (ctrl_t ctrl, struct stats_s *stats, int in_fd) stats->count++; - err = keydb_classify_name (line, &desc); + err = classify_user_id (line, &desc); if (err) { print_import_problem (ctrl, NULL, 0); diff --git a/sm/keydb.c b/sm/keydb.c index a1f0e9c18..ddf9a4830 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -949,8 +949,8 @@ keydb_search_kid (KEYDB_HANDLE hd, u32 *kid) memset (&desc, 0, sizeof desc); desc.mode = KEYDB_SEARCH_MODE_LONG_KID; -/* desc.u.kid[0] = kid[0]; */ -/* desc.u.kid[1] = kid[1]; */ + desc.u.kid[0] = kid[0]; + desc.u.kid[1] = kid[1]; return keydb_search (hd, &desc, 1); } @@ -1016,284 +1016,6 @@ keydb_search_subject (KEYDB_HANDLE hd, const char *name) } -static int -classify_user_id (const char *name, - KEYDB_SEARCH_DESC *desc, - int *force_exact ) -{ - const char *s; - int hexprefix = 0; - int hexlength; - int mode = 0; - - /* 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 */ - memset (desc, 0, sizeof *desc); - *force_exact = 0; - /* Skip leading spaces. Fixme: what about trailing white space? */ - for(s = name; *s && spacep (s); s++ ) - ; - - switch (*s) - { - case 0: /* empty string is an error */ - return 0; - - case '.': /* an email address, compare from end */ - mode = KEYDB_SEARCH_MODE_MAILEND; - s++; - desc->u.name = s; - break; - - case '<': /* an email address */ - mode = KEYDB_SEARCH_MODE_MAIL; - s++; - desc->u.name = s; - break; - - case '@': /* part of an email address */ - mode = KEYDB_SEARCH_MODE_MAILSUB; - s++; - desc->u.name = s; - break; - - case '=': /* exact compare */ - mode = KEYDB_SEARCH_MODE_EXACT; - s++; - desc->u.name = s; - break; - - case '*': /* case insensitive substring search */ - mode = KEYDB_SEARCH_MODE_SUBSTR; - s++; - desc->u.name = s; - break; - - case '+': /* compare individual words */ - mode = KEYDB_SEARCH_MODE_WORDS; - s++; - desc->u.name = s; - break; - - case '/': /* subject's DN */ - s++; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBJECT; - break; - - case '#': - { - const char *si; - - s++; - if ( *s == '/') - { /* "#/" indicates an issuer's DN */ - s++; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_ISSUER; - } - else - { /* serialnumber + optional issuer ID */ - for (si=s; *si && *si != '/'; si++) - { - if (!strchr("01234567890abcdefABCDEF", *si)) - return 0; /* invalid digit in serial number*/ - } - desc->sn = (const unsigned char*)s; - desc->snlen = -1; - if (!*si) - mode = KEYDB_SEARCH_MODE_SN; - else - { - s = si+1; - if (!*s || spacep (s)) - return 0; /* no DN or prefixed with a space */ - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_ISSUER_SN; - } - } - } - break; - - case ':': /*Unified fingerprint */ - { - const char *se, *si; - int i; - - se = strchr (++s,':'); - if (!se) - return 0; - for (i=0,si=s; si < se; si++, i++ ) - { - if (!strchr("01234567890abcdefABCDEF", *si)) - return 0; /* invalid digit */ - } - if (i != 32 && i != 40) - return 0; /* invalid length of fpr*/ - 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 0; /* Invalid. */ - mode = KEYDB_SEARCH_MODE_KEYGRIP; - } - break; - - default: - if (s[0] == '0' && s[1] == 'x') - { - hexprefix = 1; - s += 2; - } - - hexlength = strspn(s, "0123456789abcdefABCDEF"); - if (hexlength >= 8 && s[hexlength] =='!') - { - *force_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 (hexprefix) /* a "0x" prefix without correct */ - return 0; /* termination is an error */ - /* The first chars looked like a hex number, but really is - not */ - hexlength = 0; - } - - if (*force_exact) - hexlength--; /* remove the bang */ - - if (hexlength == 8 - || (!hexprefix && hexlength == 9 && *s == '0')) - { /* short keyid */ - unsigned long kid; - if (hexlength == 9) - s++; - kid = strtoul( s, NULL, 16 ); - desc->u.kid[4] = kid >> 24; - desc->u.kid[5] = kid >> 16; - desc->u.kid[6] = kid >> 8; - desc->u.kid[7] = kid; - mode = KEYDB_SEARCH_MODE_SHORT_KID; - } - else if (hexlength == 16 - || (!hexprefix && hexlength == 17 && *s == '0')) - { /* complete keyid */ - unsigned long kid0, kid1; - char buf[9]; - if (hexlength == 17) - s++; - mem2str(buf, s, 9 ); - kid0 = strtoul (buf, NULL, 16); - kid1 = strtoul (s+8, NULL, 16); - desc->u.kid[0] = kid0 >> 24; - desc->u.kid[1] = kid0 >> 16; - desc->u.kid[2] = kid0 >> 8; - desc->u.kid[3] = kid0; - desc->u.kid[4] = kid1 >> 24; - desc->u.kid[5] = kid1 >> 16; - desc->u.kid[6] = kid1 >> 8; - desc->u.kid[7] = kid1; - mode = KEYDB_SEARCH_MODE_LONG_KID; - } - 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) - { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - mode = KEYDB_SEARCH_MODE_FPR16; - } - 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) - { - int c = hextobyte(s); - if (c == -1) - return 0; - desc->u.fpr[i] = c; - } - 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))) - { - int i; - - for (i=0; i < 20; i++, s += 3) - { - int c = hextobyte(s); - if (c == -1 || (i < 19 && s[2] != ':')) - break; - desc->u.fpr[i] = c; - } - if (i == 20) - mode = KEYDB_SEARCH_MODE_FPR20; - } - if (!mode) /* default is substring search */ - { - *force_exact = 0; - desc->u.name = s; - mode = KEYDB_SEARCH_MODE_SUBSTR; - } - } - else - { /* hex number with a prefix but a wrong length */ - return 0; - } - } - - desc->mode = mode; - return mode; -} - - -int -keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc) -{ - int dummy; - KEYDB_SEARCH_DESC dummy_desc; - - if (!desc) - desc = &dummy_desc; - - if (!classify_user_id (name, desc, &dummy)) - return gpg_error (GPG_ERR_INV_NAME); - return 0; -} - /* Store the certificate in the key DB but make sure that it does not already exists. We do this simply by comparing the fingerprint. @@ -1483,7 +1205,7 @@ keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names) { for (ndesc=0, sl=names; sl; sl = sl->next) { - rc = keydb_classify_name (sl->d, desc+ndesc); + rc = classify_user_id (sl->d, desc+ndesc); if (rc) { log_error ("key `%s' not found: %s\n", diff --git a/sm/keydb.h b/sm/keydb.h index a440c5047..a62ce99cb 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -22,7 +22,7 @@ #include -#include "../kbx/keybox-search-desc.h" +#include "../common/userids.h" typedef struct keydb_handle *KEYDB_HANDLE; @@ -69,8 +69,6 @@ int keydb_search_issuer_sn (KEYDB_HANDLE hd, const char *issuer, const unsigned char *serial); int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer); -int keydb_classify_name (const char *name, KEYDB_SEARCH_DESC *desc); - int keydb_store_cert (ksba_cert_t cert, int ephemeral, int *existed); gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int ephemeral, int which, int idx, diff --git a/sm/keylist.c b/sm/keylist.c index 9b8538c84..e323b2740 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1334,7 +1334,7 @@ list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp, { for (ndesc=0, sl=names; sl; sl = sl->next) { - rc = keydb_classify_name (sl->d, desc+ndesc); + rc = classify_user_id (sl->d, desc+ndesc); if (rc) { log_error ("key `%s' not found: %s\n", diff --git a/sm/sign.c b/sm/sign.c index fd7c4ff2f..2ab8b4266 100644 --- a/sm/sign.c +++ b/sm/sign.c @@ -209,7 +209,7 @@ get_default_signer (ctrl_t ctrl) return cert; } - rc = keydb_classify_name (opt.local_user, &desc); + rc = classify_user_id (opt.local_user, &desc); if (rc) { log_error ("failed to find default signer: %s\n", gpg_strerror (rc));