Unification of the search descriptor usage.

This commit is contained in:
Werner Koch 2009-12-08 16:30:33 +00:00
parent bb861ac730
commit 9a96043be4
32 changed files with 501 additions and 599 deletions

2
NEWS
View File

@ -14,7 +14,7 @@ Noteworthy changes in version 2.1.x (under development)
* Numerical values may now be used as an alternative to the * Numerical values may now be used as an alternative to the
debug-level keywords. 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) Noteworthy changes in version 2.0.13 (2009-09-04)

View File

@ -1,3 +1,7 @@
2009-12-08 Werner Koch <wk@g10code.com>
* protect.c (agent_unprotect): Avoid compiler warning.
2009-12-08 Marcus Brinkmann <marcus@g10code.de> 2009-12-08 Marcus Brinkmann <marcus@g10code.de>
* call-pinentry.c (start_pinentry): Convert posix fd to assuan fd. * call-pinentry.c (start_pinentry): Convert posix fd to assuan fd.

View File

@ -775,6 +775,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
cleartext = NULL; /* Avoid cc warning. */
rc = do_decryption (s, n, rc = do_decryption (s, n,
passphrase, s2ksalt, s2kcount, passphrase, s2ksalt, s2kcount,
iv, 16, iv, 16,

View File

@ -1,11 +1,14 @@
2009-12-08 Werner Koch <wk@g10code.com> 2009-12-08 Werner Koch <wk@g10code.com>
* 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. * dns-cert.c (get_dns_cert): Add support for ADNS.
2009-12-08 Marcus Brinkmann <marcus@g10code.de> 2009-12-08 Marcus Brinkmann <marcus@g10code.de>
* asshelp.c (start_new_gpg_agent): Convert posix FD to assuan FD. * asshelp.c (start_new_gpg_agent): Convert posix FD to assuan FD.
* asshelp.c (start_new_gpg_agent) [HAVE_W32_SYSTEM]: Add missing * asshelp.c (start_new_gpg_agent) [HAVE_W32_SYSTEM]: Add missing
argument in assuan_socket_connect invocation. argument in assuan_socket_connect invocation.
* iobuf.c (iobuf_open_fd_or_name): Fix type of FD in function * iobuf.c (iobuf_open_fd_or_name): Fix type of FD in function

View File

@ -70,6 +70,7 @@ common_sources = \
http.c http.h \ http.c http.h \
localename.c \ localename.c \
session-env.c session-env.h \ session-env.c session-env.h \
userids.c userids.h \
helpfile.c helpfile.c
# Sources only useful without PTH. # Sources only useful without PTH.

View File

@ -1,5 +1,5 @@
/* dns-cert.c - DNS CERT code /* 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. * This file is part of GNUPG.
* *

322
common/userids.c Normal file
View File

@ -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 <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>
#include <string.h>
#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;
}

28
common/userids.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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*/

View File

@ -1,3 +1,23 @@
2009-12-08 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com> 2009-12-04 Werner Koch <wk@g10code.com>
* keygen.c (DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE): New. * keygen.c (DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE): New.

View File

@ -63,12 +63,13 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
*r_sec_avail = 0; *r_sec_avail = 0;
/* search the userid */ /* Search the userid */
classify_user_id (username, &desc); rc = classify_user_id (username, &desc);
exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR exactmatch = (desc.mode == KEYDB_SEARCH_MODE_FPR
|| desc.mode == KEYDB_SEARCH_MODE_FPR16 || desc.mode == KEYDB_SEARCH_MODE_FPR16
|| desc.mode == KEYDB_SEARCH_MODE_FPR20); || 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) { if (rc) {
log_error (_("key \"%s\" not found: %s\n"), username, g10_errstr (rc)); log_error (_("key \"%s\" not found: %s\n"), username, g10_errstr (rc));
write_status_text( STATUS_DELETE_PROBLEM, "1" ); write_status_text( STATUS_DELETE_PROBLEM, "1" );

View File

@ -293,6 +293,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
KBNODE *keyblock_out, unsigned int options, int *any ) KBNODE *keyblock_out, unsigned int options, int *any )
{ {
int rc = 0; int rc = 0;
gpg_error_t err;
PACKET pkt; PACKET pkt;
KBNODE keyblock = NULL; KBNODE keyblock = NULL;
KBNODE kbctx, node; KBNODE kbctx, node;
@ -318,11 +319,11 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
desc = xmalloc ( ndesc * sizeof *desc); desc = xmalloc ( ndesc * sizeof *desc);
for (ndesc=0, sl=users; sl; sl = sl->next) { 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++; ndesc++;
else else
log_error (_("key \"%s\" not found: %s\n"), 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 /* It would be nice to see which of the given users did

View File

@ -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 static int
skip_unusable (void *dummy, u32 *keyid, PKT_user_id *uid) 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++ ) 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) if (ctx->items[n].exact)
ctx->exact = 1; ctx->exact = 1;
if (!ctx->items[n].mode) if (err)
{ {
xfree (ctx); xfree (ctx);
return G10ERR_INV_USER_ID; return gpg_err_code (err); /* FIXME: remove gpg_err_code. */
} }
if(!include_unusable if(!include_unusable
&& ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID && ctx->items[n].mode!=KEYDB_SEARCH_MODE_SHORT_KID

View File

@ -50,9 +50,6 @@ struct server_local_s;
/* Object used to describe a keyblok node. */ /* Object used to describe a keyblok node. */
typedef struct kbnode_struct *KBNODE; 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 /* Session control object. This object is passed to most functions to

View File

@ -115,35 +115,6 @@ struct pubkey_find_info {
typedef struct keydb_handle *KEYDB_HANDLE; 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. */ /* Helper type for preference fucntions. */
union pref_hint union pref_hint
@ -221,7 +192,6 @@ char *get_last_passphrase(void);
void next_to_last_passphrase(void); void next_to_last_passphrase(void);
/*-- getkey.c --*/ /*-- getkey.c --*/
int classify_user_id( const char *name, KEYDB_SEARCH_DESC *desc);
void cache_public_key( PKT_public_key *pk ); void cache_public_key( PKT_public_key *pk );
void getkey_disable_caches(void); void getkey_disable_caches(void);
int get_pubkey( PKT_public_key *pk, u32 *keyid ); int get_pubkey( PKT_public_key *pk, u32 *keyid );

View File

@ -20,6 +20,7 @@
#ifndef GPG_KEYRING_H #ifndef GPG_KEYRING_H
#define GPG_KEYRING_H 1 #define GPG_KEYRING_H 1
#include "../common/userids.h"
typedef struct keyring_handle *KEYRING_HANDLE; typedef struct keyring_handle *KEYRING_HANDLE;

View File

@ -46,6 +46,7 @@
#include "srv.h" #include "srv.h"
#endif #endif
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
/* It seems Vista doesn't grok X_OK and so fails access() tests. /* 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 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) if(ascii_strcasecmp("pub",record)==0)
{ {
char *tok; char *tok;
gpg_error_t err;
if(work->desc.mode) if(work->desc.mode)
{ {
@ -606,11 +608,11 @@ parse_keyrec(char *keystring)
if((tok=strsep(&keystring,":"))==NULL) if((tok=strsep(&keystring,":"))==NULL)
return ret; return ret;
classify_user_id(tok,&work->desc); err = classify_user_id (tok, &work->desc);
if(work->desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID if (err || (work->desc.mode != KEYDB_SEARCH_MODE_SHORT_KID
&& work->desc.mode!=KEYDB_SEARCH_MODE_LONG_KID && work->desc.mode != KEYDB_SEARCH_MODE_LONG_KID
&& work->desc.mode!=KEYDB_SEARCH_MODE_FPR16 && work->desc.mode != KEYDB_SEARCH_MODE_FPR16
&& work->desc.mode!=KEYDB_SEARCH_MODE_FPR20) && work->desc.mode != KEYDB_SEARCH_MODE_FPR20))
{ {
work->desc.mode=KEYDB_SEARCH_MODE_NONE; work->desc.mode=KEYDB_SEARCH_MODE_NONE;
return ret; return ret;
@ -1598,6 +1600,7 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
int int
keyserver_export(strlist_t users) keyserver_export(strlist_t users)
{ {
gpg_error_t err;
strlist_t sl=NULL; strlist_t sl=NULL;
KEYDB_SEARCH_DESC desc; KEYDB_SEARCH_DESC desc;
int rc=0; int rc=0;
@ -1605,11 +1608,11 @@ keyserver_export(strlist_t users)
/* Weed out descriptors that we don't support sending */ /* Weed out descriptors that we don't support sending */
for(;users;users=users->next) for(;users;users=users->next)
{ {
classify_user_id (users->d, &desc); err = classify_user_id (users->d, &desc);
if(desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID && if (err || (desc.mode != KEYDB_SEARCH_MODE_SHORT_KID
desc.mode!=KEYDB_SEARCH_MODE_LONG_KID && && desc.mode != KEYDB_SEARCH_MODE_LONG_KID
desc.mode!=KEYDB_SEARCH_MODE_FPR16 && && desc.mode != KEYDB_SEARCH_MODE_FPR16
desc.mode!=KEYDB_SEARCH_MODE_FPR20) && desc.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; continue;
@ -1630,6 +1633,7 @@ keyserver_export(strlist_t users)
int int
keyserver_import(strlist_t users) keyserver_import(strlist_t users)
{ {
gpg_error_t err;
KEYDB_SEARCH_DESC *desc; KEYDB_SEARCH_DESC *desc;
int num=100,count=0; int num=100,count=0;
int rc=0; int rc=0;
@ -1639,13 +1643,13 @@ keyserver_import(strlist_t users)
for(;users;users=users->next) for(;users;users=users->next)
{ {
classify_user_id (users->d, &desc[count]); err = classify_user_id (users->d, &desc[count]);
if(desc[count].mode!=KEYDB_SEARCH_MODE_SHORT_KID && if (err || (desc[count].mode != KEYDB_SEARCH_MODE_SHORT_KID
desc[count].mode!=KEYDB_SEARCH_MODE_LONG_KID && && desc[count].mode != KEYDB_SEARCH_MODE_LONG_KID
desc[count].mode!=KEYDB_SEARCH_MODE_FPR16 && && desc[count].mode != KEYDB_SEARCH_MODE_FPR16
desc[count].mode!=KEYDB_SEARCH_MODE_FPR20) && 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; 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) 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++; ndesc++;
else else
log_error (_("key \"%s\" not found: %s\n"), log_error (_("key \"%s\" not found: %s\n"),
sl->d, g10_errstr (G10ERR_INV_USER_ID)); sl->d, gpg_strerror (err));
} }
} }

View File

@ -27,6 +27,7 @@
#include "cipher.h" #include "cipher.h"
#include "filter.h" #include "filter.h"
#include "../common/openpgpdefs.h" #include "../common/openpgpdefs.h"
#include "../common/userids.h"
#define DEBUG_PARSE_PACKET 1 #define DEBUG_PARSE_PACKET 1
@ -151,14 +152,16 @@ typedef struct
#define ATTRIB_IMAGE 1 #define ATTRIB_IMAGE 1
/* This is the cooked form of attributes */ /* This is the cooked form of attributes. */
struct user_attribute { struct user_attribute {
byte type; byte type;
const byte *data; const byte *data;
u32 len; u32 len;
}; };
typedef struct
/* (See also keybox-search-desc.h) */
struct gpg_pkt_user_id_s
{ {
int ref; /* reference counter */ int ref; /* reference counter */
int len; /* length of the name */ int len; /* length of the name */
@ -181,12 +184,15 @@ typedef struct
struct struct
{ {
/* TODO: Move more flags here */ /* TODO: Move more flags here */
unsigned mdc:1; unsigned int mdc:1;
unsigned ks_modify:1; unsigned int ks_modify:1;
unsigned compacted:1; unsigned int compacted:1;
} flags; } flags;
char name[1]; char name[1];
} PKT_user_id; };
typedef struct gpg_pkt_user_id_s PKT_user_id;
struct revoke_info struct revoke_info
{ {

View File

@ -787,7 +787,7 @@ find_and_check_key (const char *name, unsigned int use,
int trustlevel; int trustlevel;
if (!name || !*name) if (!name || !*name)
return gpg_error (GPG_ERR_INV_NAME); return gpg_error (GPG_ERR_INV_USER_ID);
pk = xtrycalloc (1, sizeof *pk); pk = xtrycalloc (1, sizeof *pk);
if (!pk) if (!pk)

View File

@ -220,8 +220,9 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
afx = new_armor_context (); afx = new_armor_context ();
kdbhd = keydb_new (0); kdbhd = keydb_new (0);
classify_user_id (uname, &desc); rc = classify_user_id (uname, &desc);
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; if (!rc)
rc = keydb_search (kdbhd, &desc, 1);
if (rc) { if (rc) {
log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc)); log_error (_("key \"%s\" not found: %s\n"),uname, g10_errstr (rc));
goto leave; goto leave;
@ -463,8 +464,9 @@ gen_revoke( const char *uname )
* We don't want the whole getkey stuff here but the entire keyblock * We don't want the whole getkey stuff here but the entire keyblock
*/ */
kdbhd = keydb_new (1); kdbhd = keydb_new (1);
classify_user_id (uname, &desc); rc = classify_user_id (uname, &desc);
rc = desc.mode? keydb_search (kdbhd, &desc, 1) : G10ERR_INV_USER_ID; if (!rc)
rc = keydb_search (kdbhd, &desc, 1);
if (rc) if (rc)
{ {
log_error (_("secret key \"%s\" not found: %s\n"), log_error (_("secret key \"%s\" not found: %s\n"),

View File

@ -214,9 +214,11 @@ register_trusted_keyid(u32 *keyid)
void void
register_trusted_key( const char *string ) register_trusted_key( const char *string )
{ {
gpg_error_t err;
KEYDB_SEARCH_DESC desc; 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 ); log_error(_("`%s' is not a valid long keyID\n"), string );
return; return;

View File

@ -1,3 +1,11 @@
2009-12-08 Werner Koch <wk@g10code.com>
* 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 <wk@g10code.com> 2008-12-09 Werner Koch <wk@g10code.com>
* kbxutil.c (main): Call i18n_init before init_common_subsystems. * kbxutil.c (main): Call i18n_init before init_common_subsystems.

View File

@ -48,24 +48,31 @@ typedef enum {
KEYDB_SEARCH_MODE_NEXT KEYDB_SEARCH_MODE_NEXT
} KeydbSearchMode; } 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; KeydbSearchMode mode;
int (*skipfnc)(void *,void*); /* used to be: void*, u32* */ int (*skipfnc)(void *, u32 *, gpg_pkt_user_id_t);
void *skipfncvalue; void *skipfncvalue;
const unsigned char *sn; const unsigned char *sn;
int snlen; /* -1 := sn is a hex string */ int snlen; /* -1 := sn is a hex string */
union { union {
const char *name; const char *name;
unsigned char fpr[24]; unsigned char fpr[24];
unsigned char kid[8]; u32 kid[2]; /* Note that this is in native endianess. */
unsigned char grip[20]; unsigned char grip[20];
} u; } u;
int exact; /* Use exactly this key ('!' suffix in gpg). */
}; };
struct keydb_search_desc; struct keydb_search_desc;
typedef struct keydb_search_desc KEYDB_SEARCH_DESC; typedef struct keydb_search_desc KEYDB_SEARCH_DESC;
typedef struct keydb_search_desc KEYBOX_SEARCH_DESC; typedef struct keydb_search_desc KEYBOX_SEARCH_DESC;

View File

@ -530,15 +530,29 @@ blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
The has_foo functions are used as helpers for search The has_foo functions are used as helpers for search
*/ */
static inline int 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 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 static inline int
@ -877,11 +891,11 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc)
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_SHORT_KID: 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; goto found;
break; break;
case KEYDB_SEARCH_MODE_LONG_KID: 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; goto found;
break; break;
case KEYDB_SEARCH_MODE_FPR: 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++) for (n=any_skip?0:ndesc; n < ndesc; n++)
{ {
/* if (desc[n].skipfnc */ /* if (desc[n].skipfnc */
/* && desc[n].skipfnc (desc[n].skipfncvalue, aki)) */ /* && desc[n].skipfnc (desc[n].skipfncvalue, aki, NULL)) */
/* break; */ /* break; */
} }
if (n == ndesc) if (n == ndesc)

View File

@ -1,3 +1,12 @@
2009-12-08 Werner Koch <wk@g10code.com>
* 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 <marcus@g10code.de> 2009-12-08 Marcus Brinkmann <marcus@g10code.de>
* call-dirmngr.c (start_dirmngr_ext): Convert posix fd to assuan fd. * call-dirmngr.c (start_dirmngr_ext): Convert posix fd to assuan fd.

View File

@ -301,7 +301,7 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
KEYDB_HANDLE kh = NULL; KEYDB_HANDLE kh = NULL;
ksba_cert_t cert = NULL; ksba_cert_t cert = NULL;
rc = keydb_classify_name (name, &desc); rc = classify_user_id (name, &desc);
if (!rc) if (!rc)
{ {
kh = keydb_new (0); 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; KEYDB_HANDLE kh = NULL;
*r_cert = NULL; *r_cert = NULL;
rc = keydb_classify_name (name, &desc); rc = classify_user_id (name, &desc);
if (!rc) if (!rc)
{ {
kh = keydb_new (0); kh = keydb_new (0);

View File

@ -45,7 +45,7 @@ delete_one (ctrl_t ctrl, const char *username)
int duplicates = 0; int duplicates = 0;
int is_ephem = 0; int is_ephem = 0;
rc = keydb_classify_name (username, &desc); rc = classify_user_id (username, &desc);
if (rc) if (rc)
{ {
log_error (_("certificate `%s' not found: %s\n"), log_error (_("certificate `%s' not found: %s\n"),

View File

@ -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) 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) if (rc)
{ {
log_error ("key `%s' not found: %s\n", 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; goto leave;
} }
rc = keydb_classify_name (name, desc); rc = classify_user_id (name, desc);
if (rc) if (rc)
{ {
log_error ("key `%s' not found: %s\n", log_error ("key `%s' not found: %s\n",

View File

@ -452,7 +452,7 @@ reimport_one (ctrl_t ctrl, struct stats_s *stats, int in_fd)
stats->count++; stats->count++;
err = keydb_classify_name (line, &desc); err = classify_user_id (line, &desc);
if (err) if (err)
{ {
print_import_problem (ctrl, NULL, 0); print_import_problem (ctrl, NULL, 0);

View File

@ -949,8 +949,8 @@ keydb_search_kid (KEYDB_HANDLE hd, u32 *kid)
memset (&desc, 0, sizeof desc); memset (&desc, 0, sizeof desc);
desc.mode = KEYDB_SEARCH_MODE_LONG_KID; desc.mode = KEYDB_SEARCH_MODE_LONG_KID;
/* desc.u.kid[0] = kid[0]; */ desc.u.kid[0] = kid[0];
/* desc.u.kid[1] = kid[1]; */ desc.u.kid[1] = kid[1];
return keydb_search (hd, &desc, 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 /* Store the certificate in the key DB but make sure that it does not
already exists. We do this simply by comparing the fingerprint. 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) 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) if (rc)
{ {
log_error ("key `%s' not found: %s\n", log_error ("key `%s' not found: %s\n",

View File

@ -22,7 +22,7 @@
#include <ksba.h> #include <ksba.h>
#include "../kbx/keybox-search-desc.h" #include "../common/userids.h"
typedef struct keydb_handle *KEYDB_HANDLE; 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); const char *issuer, const unsigned char *serial);
int keydb_search_subject (KEYDB_HANDLE hd, const char *issuer); 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); 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, gpg_error_t keydb_set_cert_flags (ksba_cert_t cert, int ephemeral,
int which, int idx, int which, int idx,

View File

@ -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) 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) if (rc)
{ {
log_error ("key `%s' not found: %s\n", log_error ("key `%s' not found: %s\n",

View File

@ -209,7 +209,7 @@ get_default_signer (ctrl_t ctrl)
return cert; return cert;
} }
rc = keydb_classify_name (opt.local_user, &desc); rc = classify_user_id (opt.local_user, &desc);
if (rc) if (rc)
{ {
log_error ("failed to find default signer: %s\n", gpg_strerror (rc)); log_error ("failed to find default signer: %s\n", gpg_strerror (rc));