Enhanced --auto-key-locate.

This commit is contained in:
Werner Koch 2008-04-08 11:04:16 +00:00
parent 7707a7e5f8
commit 97ec9aac2b
14 changed files with 226 additions and 96 deletions

5
NEWS
View File

@ -1,6 +1,11 @@
Noteworthy changes in version 2.0.10 (unreleased) Noteworthy changes in version 2.0.10 (unreleased)
------------------------------------------------- -------------------------------------------------
* New keyserver helper gpg2keys_kdns as generic DNS CERT lookup. Run
with --help for a short description. Requires the ADNS library.
* New mechanisms "local" and "nodefault" for --auto-key-locate [gpg].
Fixed a few problems with this option.
Noteworthy changes in version 2.0.9 (2008-03-26) Noteworthy changes in version 2.0.9 (2008-03-26)

View File

@ -1,3 +1,9 @@
2008-04-08 Werner Koch <wk@g10code.com>
* gpg.texi (GPG Configuration Options): Change subkeys.pgp.net to
keys.gnupg.net. Describe --auto-key-locate mechanisms local and
nodefault.
2008-04-03 Werner Koch <wk@g10code.com> 2008-04-03 Werner Koch <wk@g10code.com>
* yat2m.c (proc_texi_cmd): Remove extra apostrophe from @samp and * yat2m.c (proc_texi_cmd): Remove extra apostrophe from @samp and

View File

@ -1305,28 +1305,41 @@ exists.
GnuPG can automatically locate and retrieve keys as needed using this GnuPG can automatically locate and retrieve keys as needed using this
option. This happens when encrypting to an email address (in the option. This happens when encrypting to an email address (in the
"user@@example.com" form), and there are no user@@example.com keys on "user@@example.com" form), and there are no user@@example.com keys on
the local keyring. This option takes any number of the following the local keyring. This option takes any number of the following
arguments, in the order they are to be tried: mechanisms, in the order they are to be tried:
@table @asis @table @asis
@item cert @item cert
locate a key using DNS CERT, as specified in rfc4398. Locate a key using DNS CERT, as specified in rfc4398.
@item pka @item pka
locate a key using DNS PKA. Locate a key using DNS PKA.
@item ldap @item ldap
locate a key using the PGP Universal method of checking Locate a key using the PGP Universal method of checking
"ldap://keys.(thedomain)". @samp{ldap://keys.(thedomain)}.
@item keyserver @item keyserver
locate a key using whatever keyserver is defined using the Locate a key using whatever keyserver is defined using the
@option{--keyserver} option. @option{--keyserver} option.
@item (keyserver URL) @item keyserver-URL
In addition, a keyserver URL as used in the @option{--keyserver} option may be In addition, a keyserver URL as used in the @option{--keyserver} option
used here to query that particular keyserver. may be used here to query that particular keyserver.
@item local
Locate the key using the local keyrings. This mechanism allows to
select the order a local key lookup is done. Thus using
@samp{--auto-key-locate local} is identical to
@option{--no-auto-key-locate}.
@item nodefault
This flag disables the standard local key lookup, done before any of the
mechanisms defined by the @option{--auto-key-locate} are tried. The
position of this mechanism in the list does not matter. It is not
required if @code{local} is also used.
@end table @end table
@item --keyid-format @code{short|0xshort|long|0xlong} @item --keyid-format @code{short|0xshort|long|0xlong}
@ -1351,7 +1364,7 @@ from below, but apply only to this particular keyserver.
Most keyservers synchronize with each other, so there is generally no Most keyservers synchronize with each other, so there is generally no
need to send keys to more than one server. The keyserver need to send keys to more than one server. The keyserver
@code{hkp://subkeys.pgp.net} uses round robin DNS to give a different @code{hkp://keys.gnupg.net} uses round robin DNS to give a different
keyserver each time you use it. keyserver each time you use it.
@item --keyserver-options @code{name=value1 } @item --keyserver-options @code{name=value1 }

View File

@ -1,3 +1,20 @@
2008-04-08 Werner Koch <wk@g10code.com>
* options.h (opt): Add AKL_NODEFAULT and AKL_LOCAL.
* getkey.c (parse_auto_key_locate): Parse them.
(get_pubkey_byname): Implement them. Add arg NO_AKL and use that
in all cases where a local key is expected.
* import.c (import_one): Fill in the fingerprint in all cases.
Use log_get_stream.
* keyserver.c (keyserver_import_pka): Set FPR to NULL on error.
Return G10ERR_NO_PUBKEY if no PKA info is available or no key URI
is given in the PKA record..
(keyserver_import_cert): Return G10ERR_NO_PUBKEY if a CERT record
was not found.
* getkey.c (get_pubkey_byname): Release FPR in the error case.
Continue with next mechanism on error. Better diagnostics.
2008-04-07 Werner Koch <wk@g10code.com> 2008-04-07 Werner Koch <wk@g10code.com>
* keyserver.c (parse_keyserver_uri): Allow a default host name. * keyserver.c (parse_keyserver_uri): Allow a default host name.
@ -10121,7 +10138,7 @@ Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo)
Copyright 1998,1999,2000,2001,2002,2003,2004,2005, Copyright 1998,1999,2000,2001,2002,2003,2004,2005,
2006,2007 Free Software Foundation, Inc. 2006,2007,2008 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without

View File

@ -1,6 +1,6 @@
/* getkey.c - Get a key from the database /* getkey.c - Get a key from the database
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006, 2007 Free Software Foundation, Inc. * 2006, 2007, 2008 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -912,64 +912,91 @@ key_byname( GETKEY_CTX *retctx, strlist_t namelist,
/* Find a public key from NAME and return the keyblock or the key. If /* Find a public key from NAME and return the keyblock or the key. If
ret_kdb is not NULL, the KEYDB handle used to locate this keyblock ret_kdb is not NULL, the KEYDB handle used to locate this keyblock
is returned and the caller is responsible for closing it. If a key is returned and the caller is responsible for closing it. If a key
was not found and NAME is a valid RFC822 mailbox and --auto-key-locate was not found (or if local search has been disabled) and NAME is a
has been enabled, we try to import the key via the online mechanisms valid RFC822 mailbox and --auto-key-locate has been enabled, we try
defined by --auto-key-locate. */ to import the key via the online mechanisms defined by
--auto-key-locate. */
int int
get_pubkey_byname (PKT_public_key *pk, get_pubkey_byname (PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock, const char *name, KBNODE *ret_keyblock,
KEYDB_HANDLE *ret_kdbhd, int include_unusable ) KEYDB_HANDLE *ret_kdbhd, int include_unusable,
int no_akl)
{ {
int rc; int rc;
strlist_t namelist = NULL; strlist_t namelist = NULL;
struct akl *akl;
int nodefault = 0;
add_to_strlist( &namelist, name ); /* Check whether we the default local search has been disabled.
This is the case if either the "nodefault" or the "local" keyword
are in the list of auto key locate mechanisms. */
if (!no_akl)
{
for (akl=opt.auto_key_locate; akl; akl=akl->next)
if (akl->type == AKL_NODEFAULT || akl->type == AKL_LOCAL)
{
nodefault = 1;
break;
}
}
rc = key_byname( NULL, namelist, pk, NULL, 0, if (nodefault)
include_unusable, ret_keyblock, ret_kdbhd); rc = G10ERR_NO_PUBKEY;
else
{
add_to_strlist (&namelist, name);
rc = key_byname (NULL, namelist, pk, NULL, 0,
include_unusable, ret_keyblock, ret_kdbhd);
}
/* If the requested name resembles a valid mailbox and automatic /* If the requested name resembles a valid mailbox and automatic
retrieval has been enabled, we try to import the key. */ retrieval has been enabled, we try to import the key. */
if (rc == G10ERR_NO_PUBKEY && is_valid_mailbox(name)) if (rc == G10ERR_NO_PUBKEY && !no_akl && is_valid_mailbox(name))
{ {
struct akl *akl; for (akl=opt.auto_key_locate; akl; akl=akl->next)
for(akl=opt.auto_key_locate;akl;akl=akl->next)
{ {
unsigned char *fpr=NULL; unsigned char *fpr = NULL;
size_t fpr_len; size_t fpr_len;
int did_key_byname = 0;
int no_fingerprint = 0;
const char *mechanism = "?";
switch(akl->type) switch(akl->type)
{ {
case AKL_NODEFAULT:
/* This is a dummy mechanism. */
mechanism = "None";
rc = G10ERR_NO_PUBKEY;
break;
case AKL_LOCAL:
mechanism = "Local";
did_key_byname = 1;
add_to_strlist (&namelist, name);
rc = key_byname (NULL, namelist, pk, NULL, 0,
include_unusable, ret_keyblock, ret_kdbhd);
break;
case AKL_CERT: case AKL_CERT:
mechanism = "DNS CERT";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc=keyserver_import_cert(name,&fpr,&fpr_len); rc=keyserver_import_cert(name,&fpr,&fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(rc==0)
log_info(_("automatically retrieved `%s' via %s\n"),
name,"DNS CERT");
break; break;
case AKL_PKA: case AKL_PKA:
mechanism = "PKA";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc=keyserver_import_pka(name,&fpr,&fpr_len); rc=keyserver_import_pka(name,&fpr,&fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(rc==0)
log_info(_("automatically retrieved `%s' via %s\n"),
name,"PKA");
break; break;
case AKL_LDAP: case AKL_LDAP:
mechanism = "LDAP";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc=keyserver_import_ldap(name,&fpr,&fpr_len); rc=keyserver_import_ldap(name,&fpr,&fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(rc==0)
log_info(_("automatically retrieved `%s' via %s\n"),
name,"LDAP");
break; break;
case AKL_KEYSERVER: case AKL_KEYSERVER:
@ -979,32 +1006,31 @@ get_pubkey_byname (PKT_public_key *pk,
and getting a whole lot of keys back. */ and getting a whole lot of keys back. */
if(opt.keyserver) if(opt.keyserver)
{ {
mechanism = opt.keyserver->uri;
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc=keyserver_import_name(name,&fpr,&fpr_len,opt.keyserver); rc=keyserver_import_name(name,&fpr,&fpr_len,opt.keyserver);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(rc==0)
log_info(_("automatically retrieved `%s' via %s\n"),
name,opt.keyserver->uri);
} }
else
{
mechanism = "Unconfigured keyserver";
rc = G10ERR_NO_PUBKEY;
}
break; break;
case AKL_SPEC: case AKL_SPEC:
{ {
struct keyserver_spec *keyserver; struct keyserver_spec *keyserver;
mechanism = akl->spec->uri;
keyserver=keyserver_match(akl->spec); keyserver=keyserver_match(akl->spec);
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc=keyserver_import_name(name,&fpr,&fpr_len,keyserver); rc=keyserver_import_name(name,&fpr,&fpr_len,keyserver);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(rc==0)
log_info(_("automatically retrieved `%s' via %s\n"),
name,akl->spec->uri);
} }
break; break;
} }
/* Use the fingerprint of the key that we actually fetched. /* Use the fingerprint of the key that we actually fetched.
This helps prevent problems where the key that we fetched This helps prevent problems where the key that we fetched
doesn't have the same name that we used to fetch it. In doesn't have the same name that we used to fetch it. In
@ -1027,14 +1053,29 @@ get_pubkey_byname (PKT_public_key *pk,
log_info("auto-key-locate found fingerprint %s\n",fpr_string); log_info("auto-key-locate found fingerprint %s\n",fpr_string);
add_to_strlist( &namelist, fpr_string ); add_to_strlist( &namelist, fpr_string );
xfree(fpr);
} }
else if (!rc && !fpr && !did_key_byname)
{
no_fingerprint = 1;
rc = G10ERR_NO_PUBKEY;
}
xfree (fpr);
fpr = NULL;
rc = key_byname( NULL, namelist, pk, NULL, 0, if (!rc && !did_key_byname)
include_unusable, ret_keyblock, ret_kdbhd); rc = key_byname (NULL, namelist, pk, NULL, 0,
if(rc!=G10ERR_NO_PUBKEY) include_unusable, ret_keyblock, ret_kdbhd);
break; if (!rc)
{
/* Key found. */
log_info (_("automatically retrieved `%s' via %s\n"),
name, mechanism);
break;
}
if (rc != G10ERR_NO_PUBKEY || opt.verbose || no_fingerprint)
log_info (_("error retrieving `%s' via %s: %s\n"),
name, mechanism,
no_fingerprint? _("No fingerprint"):g10_errstr(rc));
} }
} }
@ -2638,7 +2679,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
rc = 0; rc = 0;
while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems))) { while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems))) {
/* If we are searching for the first key we have to make sure /* If we are searching for the first key we have to make sure
that the next interation does not no an implicit reset. that the next iteration does not do an implicit reset.
This can be triggered by an empty key ring. */ This can be triggered by an empty key ring. */
if (ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST) if (ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST)
ctx->items->mode = KEYDB_SEARCH_MODE_NEXT; ctx->items->mode = KEYDB_SEARCH_MODE_NEXT;
@ -2949,6 +2990,7 @@ release_akl(void)
} }
} }
/* Returns false on error. */
int int
parse_auto_key_locate(char *options) parse_auto_key_locate(char *options)
{ {
@ -2964,7 +3006,11 @@ parse_auto_key_locate(char *options)
akl=xmalloc_clear(sizeof(*akl)); akl=xmalloc_clear(sizeof(*akl));
if(ascii_strcasecmp(tok,"ldap")==0) if(ascii_strcasecmp(tok,"nodefault")==0)
akl->type=AKL_NODEFAULT;
else if(ascii_strcasecmp(tok,"local")==0)
akl->type=AKL_LOCAL;
else if(ascii_strcasecmp(tok,"ldap")==0)
akl->type=AKL_LDAP; akl->type=AKL_LDAP;
else if(ascii_strcasecmp(tok,"keyserver")==0) else if(ascii_strcasecmp(tok,"keyserver")==0)
akl->type=AKL_KEYSERVER; akl->type=AKL_KEYSERVER;

View File

@ -704,6 +704,7 @@ static ARGPARSE_OPTS opts[] = {
I'm returning the favor. */ I'm returning the favor. */
{ oLocalUser, "sign-with", 2, "@" }, { oLocalUser, "sign-with", 2, "@" },
{ oRecipient, "user", 2, "@" }, { oRecipient, "user", 2, "@" },
{ oRequireCrossCert, "require-backsigs", 0, "@"}, { oRequireCrossCert, "require-backsigs", 0, "@"},
{ oRequireCrossCert, "require-cross-certification", 0, "@"}, { oRequireCrossCert, "require-cross-certification", 0, "@"},
{ oNoRequireCrossCert, "no-require-backsigs", 0, "@"}, { oNoRequireCrossCert, "no-require-backsigs", 0, "@"},
@ -1549,6 +1550,8 @@ gpgconf_list (const char *configfile)
printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE); printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE); printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE);
printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE); printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
printf ("allow-pka-lookup:%lu:\n", GC_OPT_FLAG_NONE);
xfree (configfile_esc); xfree (configfile_esc);
} }

View File

@ -682,7 +682,7 @@ check_prefs(KBNODE keyblock)
* Try to import one keyblock. Return an error only in serious cases, but * Try to import one keyblock. Return an error only in serious cases, but
* never for an invalid keyblock. It uses log_error to increase the * never for an invalid keyblock. It uses log_error to increase the
* internal errorcount, so that invalid input can be detected by programs * internal errorcount, so that invalid input can be detected by programs
* which called g10. * which called gpg.
*/ */
static int static int
import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
@ -697,6 +697,7 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
int rc = 0; int rc = 0;
int new_key = 0; int new_key = 0;
int mod_key = 0; int mod_key = 0;
int same_key = 0;
int non_self = 0; int non_self = 0;
/* get the key and print some info about it */ /* get the key and print some info about it */
@ -715,12 +716,14 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
nbits_from_pk( pk ), nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ), pubkey_letter( pk->pubkey_algo ),
keystr_from_pk(pk), datestr_from_pk(pk) ); keystr_from_pk(pk), datestr_from_pk(pk) );
if( uidnode ) if (uidnode)
print_utf8_string( stderr, uidnode->pkt->pkt.user_id->name, print_utf8_string (log_get_stream (),
uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len ); uidnode->pkt->pkt.user_id->len );
log_printf ("\n"); log_printf ("\n");
} }
if( !uidnode ) if( !uidnode )
{ {
log_error( _("key %s: no user ID\n"), keystr_from_pk(pk)); log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
@ -958,7 +961,8 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
} }
else else
{ {
if (is_status_enabled ()) same_key = 1;
if (is_status_enabled ())
print_import_ok (pk, NULL, 0); print_import_ok (pk, NULL, 0);
if( !opt.quiet ) if( !opt.quiet )
@ -975,6 +979,33 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
} }
leave: leave:
if (mod_key || new_key || same_key)
{
/* A little explanation for this: we fill in the fingerprint
when importing keys as it can be useful to know the
fingerprint in certain keyserver-related cases (a keyserver
asked for a particular name, but the key doesn't have that
name). However, in cases where we're importing more than
one key at a time, we cannot know which key to fingerprint.
In these cases, rather than guessing, we do not
fingerprinting at all, and we must hope the user ID on the
keys are useful. Note that we need to do this for new
keys, merged keys and even for unchanged keys. This is
required because for example the --auto-key-locate feature
may import an already imported key and needs to know the
fingerprint of the key in all cases. */
if (fpr)
{
xfree (*fpr);
/* Note that we need to compare against 0 here because
COUNT gets only incremented after returning form this
function. */
if (stats->count == 0)
*fpr = fingerprint_from_pk (pk, NULL, fpr_len);
else
*fpr = NULL;
}
}
/* Now that the key is definitely incorporated into the keydb, we /* Now that the key is definitely incorporated into the keydb, we
need to check if a designated revocation is present or if the need to check if a designated revocation is present or if the
@ -988,24 +1019,6 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
} }
else if(new_key) else if(new_key)
{ {
/* A little explanation for this: we fill in the fingerprint
when importing keys as it can be useful to know the
fingerprint in certain keyserver-related cases (a keyserver
asked for a particular name, but the key doesn't have that
name). However, in cases where we're importing more than
one key at a time, we cannot know which key to fingerprint.
In these cases, rather than guessing, we do not fingerpring
at all, and we must hope the user ID on the keys are
useful. */
if(fpr)
{
xfree(*fpr);
if(stats->imported==1)
*fpr=fingerprint_from_pk(pk,NULL,fpr_len);
else
*fpr=NULL;
}
revocation_present(keyblock); revocation_present(keyblock);
if(!from_sk && seckey_available(keyid)==0) if(!from_sk && seckey_available(keyid)==0)
check_prefs(keyblock); check_prefs(keyblock);

View File

@ -223,7 +223,7 @@ int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
KBNODE get_pubkeyblock( u32 *keyid ); KBNODE get_pubkeyblock( u32 *keyid );
int get_pubkey_byname( PKT_public_key *pk, const char *name, int get_pubkey_byname( PKT_public_key *pk, const char *name,
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd, KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
int include_unusable ); int include_unusable, int no_akl );
int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk, int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,
strlist_t names, KBNODE *ret_keyblock ); strlist_t names, KBNODE *ret_keyblock );
int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock ); int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock );

View File

@ -1544,7 +1544,7 @@ keyedit_menu( const char *username, strlist_t locusr,
#endif #endif
/* Get the public key */ /* Get the public key */
rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1); rc = get_pubkey_byname (NULL, username, &keyblock, &kdbhd, 1, 1);
if( rc ) if( rc )
goto leave; goto leave;
if( fix_keyblock( keyblock ) ) if( fix_keyblock( keyblock ) )
@ -3396,7 +3396,7 @@ menu_addrevoker( KBNODE pub_keyblock, KBNODE sec_keyblock, int sensitive )
GnuPG both can handle a designated revokation from a GnuPG both can handle a designated revokation from a
subkey. */ subkey. */
revoker_pk->req_usage=PUBKEY_USAGE_CERT; revoker_pk->req_usage=PUBKEY_USAGE_CERT;
rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1); rc=get_pubkey_byname(revoker_pk,answer,NULL,NULL,1, 1);
if(rc) if(rc)
{ {
log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc)); log_error (_("key \"%s\" not found: %s\n"),answer,g10_errstr(rc));

View File

@ -1,6 +1,6 @@
/* keyserver.c - generic keyserver code /* keyserver.c - generic keyserver code
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
* 2007 Free Software Foundation, Inc. * 2007, 2008 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -2008,7 +2008,14 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
*domain='.'; *domain='.';
type=get_dns_cert(look,max_cert_size,&key,fpr,fpr_len,&url); type=get_dns_cert(look,max_cert_size,&key,fpr,fpr_len,&url);
if(type==1) if (!type || type == -1)
{
/* There might be an error in res_query which leads to an error
return (-1) in the case that nothing was found. Thus we take
all errors as key not found. */
rc = G10ERR_NO_PUBKEY;
}
else if (type==1)
{ {
int armor_status=opt.no_armor; int armor_status=opt.no_armor;
@ -2072,26 +2079,30 @@ int
keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len) keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len)
{ {
char *uri; char *uri;
int rc=-1; int rc = G10ERR_NO_PUBKEY;
*fpr=xmalloc(20); *fpr = xmalloc (20);
*fpr_len=20; *fpr_len = 20;
uri = get_pka_info (name, *fpr); uri = get_pka_info (name, *fpr);
if (uri) if (uri && *uri)
{ {
/* An URI is available. Lookup the key. */
struct keyserver_spec *spec; struct keyserver_spec *spec;
spec = parse_keyserver_uri (uri, 1, NULL, 0); spec = parse_keyserver_uri (uri, 1, NULL, 0);
if (spec) if (spec)
{ {
rc=keyserver_import_fprint (*fpr, 20, spec); rc = keyserver_import_fprint (*fpr, 20, spec);
free_keyserver_spec (spec); free_keyserver_spec (spec);
} }
xfree (uri); xfree (uri);
} }
if(rc!=0) if (rc)
xfree(*fpr); {
xfree(*fpr);
*fpr = NULL;
}
return rc; return rc;
} }

View File

@ -235,7 +235,15 @@ struct
keyring. */ keyring. */
struct akl struct akl
{ {
enum {AKL_CERT, AKL_PKA, AKL_LDAP, AKL_KEYSERVER, AKL_SPEC} type; enum {
AKL_NODEFAULT,
AKL_LOCAL,
AKL_CERT,
AKL_PKA,
AKL_LDAP,
AKL_KEYSERVER,
AKL_SPEC
} type;
struct keyserver_spec *spec; struct keyserver_spec *spec;
struct akl *next; struct akl *next;
} *auto_key_locate; } *auto_key_locate;

View File

@ -824,8 +824,9 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
pk->req_usage = use; pk->req_usage = use;
/* We explicitly allow encrypt-to to an disabled key; thus /* We explicitly allow encrypt-to to an disabled key; thus
we pass 1 as last argument. */ we pass 1for the second last argument and 1 as the last
if ( (rc = get_pubkey_byname ( pk, rov->d, NULL, NULL, 1 )) ) argument to disable AKL. */
if ( (rc = get_pubkey_byname (pk, rov->d, NULL, NULL, 1, 1)) )
{ {
free_public_key ( pk ); pk = NULL; free_public_key ( pk ); pk = NULL;
log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
@ -964,7 +965,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
free_public_key (pk); free_public_key (pk);
pk = xmalloc_clear( sizeof *pk ); pk = xmalloc_clear( sizeof *pk );
pk->req_usage = use; pk->req_usage = use;
rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); rc = get_pubkey_byname( pk, answer, NULL, NULL, 0, 0 );
if (rc) if (rc)
tty_printf(_("No such user ID.\n")); tty_printf(_("No such user ID.\n"));
else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) )
@ -1037,8 +1038,8 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
pk->req_usage = use; pk->req_usage = use;
/* The default recipient is allowed to be disabled; thus pass 1 /* The default recipient is allowed to be disabled; thus pass 1
as last argument. */ as second last argument. We also don't want an AKL. */
rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1); rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1, 1);
if (rc) if (rc)
log_error(_("unknown default recipient \"%s\"\n"), def_rec ); log_error(_("unknown default recipient \"%s\"\n"), def_rec );
else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) ) else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) )
@ -1078,7 +1079,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
pk = xmalloc_clear( sizeof *pk ); pk = xmalloc_clear( sizeof *pk );
pk->req_usage = use; pk->req_usage = use;
if ( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) if ( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0, 0 )) )
{ {
/* Key not found or other error. */ /* Key not found or other error. */
free_public_key( pk ); pk = NULL; free_public_key( pk ); pk = NULL;

View File

@ -1,3 +1,7 @@
2008-04-08 Werner Koch <wk@g10code.com>
* gpgconf-comp.c (gc_options_gpg): Add --auto-key-locate.
2008-03-26 Werner Koch <wk@g10code.com> 2008-03-26 Werner Koch <wk@g10code.com>
* make-dns-cert.c: Include unistd.h. Use config.h if requested. * make-dns-cert.c: Include unistd.h. Use config.h if requested.

View File

@ -681,6 +681,9 @@ static gc_option_t gc_options_gpg[] =
{ "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
"gnupg", N_("allow PKA lookups (DNS requests)"), "gnupg", N_("allow PKA lookups (DNS requests)"),
GC_ARG_TYPE_NONE, GC_BACKEND_GPG }, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
{ "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
"gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
GC_OPTION_NULL GC_OPTION_NULL