mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-10 18:03:03 +01:00
auto retrieve keys from PKA. Thsi allows to specify an email address
so that gpg can get the key from DNS. This helps with opportunistic encryption. No integration with the trust modell yet.
This commit is contained in:
parent
433038b4a9
commit
2ce542ad52
@ -1,3 +1,21 @@
|
|||||||
|
2005-08-05 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgv.c (keyserver_import_fprint): New stub.
|
||||||
|
|
||||||
|
* keygen.c (ask_user_id): Moved email checking code out to ..
|
||||||
|
* misc.c (is_valid_mailbox): .. new.
|
||||||
|
* mainproc.c (get_pka_address): Use it here.
|
||||||
|
* getkey.c (get_pubkey_byname): Add falback to auto-retrieve a key
|
||||||
|
via the PKA mechanism.
|
||||||
|
|
||||||
|
* options.h (KEYSERVER_AUTO_PKA_RETRIEVE): New.
|
||||||
|
* keyserver.c (keyserver_opts): Ditto.
|
||||||
|
* mainproc.c (check_sig_and_print): Use it here to retrieve keys
|
||||||
|
from a PKA DNS record.
|
||||||
|
|
||||||
|
* pkclist.c (build_pk_list): Add comments to this function;
|
||||||
|
re-indented it.
|
||||||
|
|
||||||
2005-08-04 David Shaw <dshaw@jabberwocky.com>
|
2005-08-04 David Shaw <dshaw@jabberwocky.com>
|
||||||
|
|
||||||
* keygen.c (proc_parameter_file): Sanity check items in keygen
|
* keygen.c (proc_parameter_file): Sanity check items in keygen
|
||||||
|
46
g10/getkey.c
46
g10/getkey.c
@ -35,6 +35,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "trustdb.h"
|
#include "trustdb.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
#include "keyserver-internal.h"
|
||||||
|
|
||||||
#define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE
|
#define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE
|
||||||
#define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE
|
#define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE
|
||||||
@ -886,22 +887,57 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a public key from NAME and returh the keyblock or the key.
|
|
||||||
* If ret_kdb is not NULL, the KEYDB handle used to locate this keyblock is
|
/* Find a public key from NAME and return the keyblock or the key. If
|
||||||
* returned and the caller is responsible for closing it.
|
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
|
||||||
|
was not found and NAME is a valid RFC822 mailbox and PKA retrieval
|
||||||
|
has been enabled, we try to import the pkea via the PKA
|
||||||
|
mechanism. */
|
||||||
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 rc;
|
int rc;
|
||||||
|
int again = 0;
|
||||||
STRLIST namelist = NULL;
|
STRLIST namelist = NULL;
|
||||||
|
|
||||||
add_to_strlist( &namelist, name );
|
add_to_strlist( &namelist, name );
|
||||||
|
retry:
|
||||||
rc = key_byname( NULL, namelist, pk, NULL, 0,
|
rc = key_byname( NULL, namelist, pk, NULL, 0,
|
||||||
include_unusable, ret_keyblock, ret_kdbhd);
|
include_unusable, ret_keyblock, ret_kdbhd);
|
||||||
|
if (rc == G10ERR_NO_PUBKEY
|
||||||
|
&& !again
|
||||||
|
&& (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE)
|
||||||
|
&& is_valid_mailbox (name))
|
||||||
|
{
|
||||||
|
/* If the requested name resembles a valid mailbox and
|
||||||
|
automatic retrieval via PKA records has been enabled, we
|
||||||
|
try to import the key via the URI and try again. */
|
||||||
|
unsigned char fpr[MAX_FINGERPRINT_LEN];
|
||||||
|
char *uri;
|
||||||
|
struct keyserver_spec *spec;
|
||||||
|
|
||||||
|
uri = get_pka_info (name, fpr);
|
||||||
|
if (uri)
|
||||||
|
{
|
||||||
|
spec = parse_keyserver_uri (uri, 0, NULL, 0);
|
||||||
|
if (spec)
|
||||||
|
{
|
||||||
|
glo_ctrl.in_auto_key_retrieve++;
|
||||||
|
if (!keyserver_import_fprint (fpr, 20, spec))
|
||||||
|
again = 1;
|
||||||
|
glo_ctrl.in_auto_key_retrieve--;
|
||||||
|
free_keyserver_spec (spec);
|
||||||
|
}
|
||||||
|
xfree (uri);
|
||||||
|
}
|
||||||
|
if (again)
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
free_strlist( namelist );
|
free_strlist( namelist );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
12
g10/gpgv.c
12
g10/gpgv.c
@ -280,6 +280,18 @@ keyserver_import_keyid( u32 *keyid, void *dummy )
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Stub:
|
||||||
|
* Because we only work with trusted keys, it does not make sense to
|
||||||
|
* get them from a keyserver
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
keyserver_import_fprint (const byte *fprint, size_t fprint_len,
|
||||||
|
struct keyserver_spec *keyserver)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Stub:
|
/* Stub:
|
||||||
* No encryption here but mainproc links to these functions.
|
* No encryption here but mainproc links to these functions.
|
||||||
*/
|
*/
|
||||||
|
@ -1655,12 +1655,7 @@ ask_user_id( int mode )
|
|||||||
cpr_kill_prompt();
|
cpr_kill_prompt();
|
||||||
if( !*amail || opt.allow_freeform_uid )
|
if( !*amail || opt.allow_freeform_uid )
|
||||||
break; /* no email address is okay */
|
break; /* no email address is okay */
|
||||||
else if( has_invalid_email_chars(amail)
|
else if ( !is_valid_mailbox (amail) )
|
||||||
|| string_count_chr(amail,'@') != 1
|
|
||||||
|| *amail == '@'
|
|
||||||
|| amail[strlen(amail)-1] == '@'
|
|
||||||
|| amail[strlen(amail)-1] == '.'
|
|
||||||
|| strstr(amail, "..") )
|
|
||||||
tty_printf(_("Not a valid email address\n"));
|
tty_printf(_("Not a valid email address\n"));
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -69,6 +69,7 @@ static struct parse_options keyserver_opts[]=
|
|||||||
{"keep-temp-files",KEYSERVER_KEEP_TEMP_FILES,NULL},
|
{"keep-temp-files",KEYSERVER_KEEP_TEMP_FILES,NULL},
|
||||||
{"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL},
|
{"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL},
|
||||||
{"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL},
|
{"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL},
|
||||||
|
{"auto-pka-retrieve",KEYSERVER_AUTO_PKA_RETRIEVE,NULL},
|
||||||
{"try-dns-srv",KEYSERVER_TRY_DNS_SRV,NULL},
|
{"try-dns-srv",KEYSERVER_TRY_DNS_SRV,NULL},
|
||||||
{"honor-keyserver-url",KEYSERVER_HONOR_KEYSERVER_URL,NULL},
|
{"honor-keyserver-url",KEYSERVER_HONOR_KEYSERVER_URL,NULL},
|
||||||
{NULL,0,NULL}
|
{NULL,0,NULL}
|
||||||
|
@ -126,6 +126,7 @@ int parse_options(char *str,unsigned int *options,
|
|||||||
struct parse_options *opts,int noisy);
|
struct parse_options *opts,int noisy);
|
||||||
char *unescape_percent_string (const unsigned char *s);
|
char *unescape_percent_string (const unsigned char *s);
|
||||||
int has_invalid_email_chars (const char *s);
|
int has_invalid_email_chars (const char *s);
|
||||||
|
int is_valid_mailbox (const char *name);
|
||||||
char *default_homedir (void);
|
char *default_homedir (void);
|
||||||
const char *get_libexecdir (void);
|
const char *get_libexecdir (void);
|
||||||
|
|
||||||
|
@ -1334,7 +1334,7 @@ get_pka_address (PKT_signature *sig)
|
|||||||
memcpy (pka->email, p, n2);
|
memcpy (pka->email, p, n2);
|
||||||
pka->email[n2] = 0;
|
pka->email[n2] = 0;
|
||||||
|
|
||||||
if (has_invalid_email_chars (pka->email))
|
if (!is_valid_mailbox (pka->email))
|
||||||
{
|
{
|
||||||
/* We don't accept invalid mail addresses. */
|
/* We don't accept invalid mail addresses. */
|
||||||
xfree (pka);
|
xfree (pka);
|
||||||
@ -1502,12 +1502,15 @@ check_sig_and_print( CTX c, KBNODE node )
|
|||||||
|
|
||||||
/* If the preferred keyserver thing above didn't work, our second
|
/* If the preferred keyserver thing above didn't work, our second
|
||||||
try is to use the URI from a DNS PKA record. */
|
try is to use the URI from a DNS PKA record. */
|
||||||
if ( rc == G10ERR_NO_PUBKEY )
|
if ( rc == G10ERR_NO_PUBKEY
|
||||||
|
&& (opt.keyserver_options.options&KEYSERVER_AUTO_PKA_RETRIEVE))
|
||||||
{
|
{
|
||||||
const char *uri = pka_uri_from_sig (sig);
|
const char *uri = pka_uri_from_sig (sig);
|
||||||
|
|
||||||
if (uri)
|
if (uri)
|
||||||
{
|
{
|
||||||
|
/* FIXME: We might want to locate the key using the
|
||||||
|
fingerprint instead of the keyid. */
|
||||||
int res;
|
int res;
|
||||||
struct keyserver_spec *spec;
|
struct keyserver_spec *spec;
|
||||||
|
|
||||||
|
14
g10/misc.c
14
g10/misc.c
@ -1088,6 +1088,20 @@ has_invalid_email_chars (const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether NAME represents a valid mailbox according to
|
||||||
|
RFC822. Returns true if so. */
|
||||||
|
int
|
||||||
|
is_valid_mailbox (const char *name)
|
||||||
|
{
|
||||||
|
return !( !name
|
||||||
|
|| !*name
|
||||||
|
|| has_invalid_email_chars (name)
|
||||||
|
|| string_count_chr (name,'@') != 1
|
||||||
|
|| *name == '@'
|
||||||
|
|| name[strlen(name)-1] == '@'
|
||||||
|
|| name[strlen(name)-1] == '.'
|
||||||
|
|| strstr (name, "..") );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is a helper function to load a Windows function from either of
|
/* This is a helper function to load a Windows function from either of
|
||||||
|
@ -299,5 +299,6 @@ struct {
|
|||||||
#define KEYSERVER_AUTO_KEY_RETRIEVE (1<<5)
|
#define KEYSERVER_AUTO_KEY_RETRIEVE (1<<5)
|
||||||
#define KEYSERVER_TRY_DNS_SRV (1<<6)
|
#define KEYSERVER_TRY_DNS_SRV (1<<6)
|
||||||
#define KEYSERVER_HONOR_KEYSERVER_URL (1<<7)
|
#define KEYSERVER_HONOR_KEYSERVER_URL (1<<7)
|
||||||
|
#define KEYSERVER_AUTO_PKA_RETRIEVE (1<<8)
|
||||||
|
|
||||||
#endif /*G10_OPTIONS_H*/
|
#endif /*G10_OPTIONS_H*/
|
||||||
|
217
g10/pkclist.c
217
g10/pkclist.c
@ -1,6 +1,6 @@
|
|||||||
/* pkclist.c
|
/* pkclist.c
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
|
||||||
* 2004 Free Software Foundation, Inc.
|
* 2004, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -744,8 +744,30 @@ expand_group(STRLIST input)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the central function to collect the keys for recipients.
|
||||||
|
It is thus used to prepare a public key encryption. encrypt-to
|
||||||
|
keys, default keys and the keys for the actual recipients are all
|
||||||
|
collected here. When not in batch mode and no recipient has been
|
||||||
|
passed on the commandline, the function will also ask for
|
||||||
|
recipients.
|
||||||
|
|
||||||
|
RCPTS is a string list with the recipients; NULL is an allowed
|
||||||
|
value but not very useful. Group expansion is done on these names;
|
||||||
|
they may be in any of the user Id formats we can handle. The flags
|
||||||
|
bits for each string in the string list are used for:
|
||||||
|
Bit 0: This is an encrypt-to recipient.
|
||||||
|
Bit 1: This is a hidden recipient.
|
||||||
|
|
||||||
|
USE is the desired use for the key - usually PUBKEY_USAGE_ENC.
|
||||||
|
RET_PK_LIST.
|
||||||
|
|
||||||
|
On success a list of keys is stored at the address RET_PK_LIST; the
|
||||||
|
caller must free this list. On error the value at this address is
|
||||||
|
not changed.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use )
|
||||||
{
|
{
|
||||||
PK_LIST pk_list = NULL;
|
PK_LIST pk_list = NULL;
|
||||||
PKT_public_key *pk=NULL;
|
PKT_public_key *pk=NULL;
|
||||||
@ -754,18 +776,24 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
STRLIST rov,remusr;
|
STRLIST rov,remusr;
|
||||||
char *def_rec = NULL;
|
char *def_rec = NULL;
|
||||||
|
|
||||||
|
/* Try to expand groups if any have been defined. */
|
||||||
if (opt.grouplist)
|
if (opt.grouplist)
|
||||||
remusr = expand_group (rcpts);
|
remusr = expand_group (rcpts);
|
||||||
else
|
else
|
||||||
remusr = rcpts;
|
remusr = rcpts;
|
||||||
|
|
||||||
/* check whether there are any recipients in the list and build the
|
/* Check whether there are any recipients in the list and build the
|
||||||
* list of the encrypt-to ones (we always trust them) */
|
* list of the encrypt-to ones (we always trust them). */
|
||||||
for( rov = remusr; rov; rov = rov->next ) {
|
for ( rov = remusr; rov; rov = rov->next )
|
||||||
|
{
|
||||||
if ( !(rov->flags & 1) )
|
if ( !(rov->flags & 1) )
|
||||||
{
|
{
|
||||||
|
/* This is a regular recipient; i.e. not an encrypt-to
|
||||||
|
one. */
|
||||||
any_recipients = 1;
|
any_recipients = 1;
|
||||||
|
|
||||||
|
/* Hidden recipients are not allowed while in PGP mode,
|
||||||
|
issue a warning and switch into GnuPG mode. */
|
||||||
if ((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8))
|
if ((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8))
|
||||||
{
|
{
|
||||||
log_info(_("you may not use %s while in %s mode\n"),
|
log_info(_("you may not use %s while in %s mode\n"),
|
||||||
@ -775,26 +803,35 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
compliance_failure();
|
compliance_failure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) {
|
else if ( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to )
|
||||||
|
{
|
||||||
|
/* Encryption has been requested and --encrypt-to has not
|
||||||
|
been disabled. Check this encrypt-to key. */
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
pk->req_usage = use;
|
pk->req_usage = use;
|
||||||
/* We can encrypt-to a disabled key */
|
|
||||||
if( (rc = get_pubkey_byname( pk, rov->d, NULL, NULL, 1 )) ) {
|
/* We explicitly allow encrypt-to to an disabled key; thus
|
||||||
|
we pass 1 as last argument. */
|
||||||
|
if ( (rc = get_pubkey_byname ( pk, rov->d, NULL, NULL, 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) );
|
||||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||||
rov->d, strlen (rov->d), -1);
|
rov->d, strlen (rov->d), -1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
|
else if ( !(rc=check_pubkey_algo2 (pk->pubkey_algo, use )) )
|
||||||
|
{
|
||||||
/* Skip the actual key if the key is already present
|
/* Skip the actual key if the key is already present
|
||||||
* in the list */
|
* in the list. Add it to our list if not. */
|
||||||
if (key_present_in_pk_list(pk_list, pk) == 0) {
|
if (key_present_in_pk_list(pk_list, pk) == 0)
|
||||||
|
{
|
||||||
free_public_key (pk); pk = NULL;
|
free_public_key (pk); pk = NULL;
|
||||||
log_info (_("%s: skipped: public key already present\n"),
|
log_info (_("%s: skipped: public key already present\n"),
|
||||||
rov->d);
|
rov->d);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
PK_LIST r;
|
PK_LIST r;
|
||||||
r = xmalloc( sizeof *r );
|
r = xmalloc( sizeof *r );
|
||||||
r->pk = pk; pk = NULL;
|
r->pk = pk; pk = NULL;
|
||||||
@ -802,7 +839,10 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
r->flags = (rov->flags&2)?1:0;
|
r->flags = (rov->flags&2)?1:0;
|
||||||
pk_list = r;
|
pk_list = r;
|
||||||
|
|
||||||
if(r->flags&1 && (PGP2 || PGP6 || PGP7 || PGP8))
|
/* Hidden encrypt-to recipients are not allowed while
|
||||||
|
in PGP mode, issue a warning and switch into
|
||||||
|
GnuPG mode. */
|
||||||
|
if ((r->flags&1) && (PGP2 || PGP6 || PGP7 || PGP8))
|
||||||
{
|
{
|
||||||
log_info(_("you may not use %s while in %s mode\n"),
|
log_info(_("you may not use %s while in %s mode\n"),
|
||||||
"--hidden-encrypt-to",
|
"--hidden-encrypt-to",
|
||||||
@ -812,7 +852,10 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
|
/* The public key is not usable for encryption or not
|
||||||
|
available. */
|
||||||
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) );
|
||||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||||
@ -822,7 +865,10 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !any_recipients && !opt.batch ) { /* ask */
|
/* If we don't have any recipients yet and we are not in batch mode
|
||||||
|
drop into interactive selection mode. */
|
||||||
|
if ( !any_recipients && !opt.batch )
|
||||||
|
{
|
||||||
int have_def_rec;
|
int have_def_rec;
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
STRLIST backlog = NULL;
|
STRLIST backlog = NULL;
|
||||||
@ -832,20 +878,27 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
def_rec = default_recipient();
|
def_rec = default_recipient();
|
||||||
have_def_rec = !!def_rec;
|
have_def_rec = !!def_rec;
|
||||||
if ( !have_def_rec )
|
if ( !have_def_rec )
|
||||||
tty_printf(_(
|
tty_printf(_("You did not specify a user ID. (you may use \"-r\")\n"));
|
||||||
"You did not specify a user ID. (you may use \"-r\")\n"));
|
|
||||||
for(;;) {
|
for (;;)
|
||||||
|
{
|
||||||
rc = 0;
|
rc = 0;
|
||||||
xfree(answer);
|
xfree(answer);
|
||||||
if( have_def_rec ) {
|
if ( have_def_rec )
|
||||||
|
{
|
||||||
|
/* A default recipient is taken as the first entry. */
|
||||||
answer = def_rec;
|
answer = def_rec;
|
||||||
def_rec = NULL;
|
def_rec = NULL;
|
||||||
}
|
}
|
||||||
else if(backlog) {
|
else if (backlog)
|
||||||
|
{
|
||||||
|
/* This is part of our trick to expand and display groups. */
|
||||||
answer = pop_strlist (&backlog);
|
answer = pop_strlist (&backlog);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Show the list of already collected recipients and ask
|
||||||
|
for more. */
|
||||||
PK_LIST iter;
|
PK_LIST iter;
|
||||||
|
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
@ -875,16 +928,25 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
}
|
}
|
||||||
|
|
||||||
answer = cpr_get_utf8("pklist.user_id.enter",
|
answer = cpr_get_utf8("pklist.user_id.enter",
|
||||||
_("\nEnter the user ID. End with an empty line: "));
|
_("\nEnter the user ID. "
|
||||||
|
"End with an empty line: "));
|
||||||
trim_spaces(answer);
|
trim_spaces(answer);
|
||||||
cpr_kill_prompt();
|
cpr_kill_prompt();
|
||||||
}
|
}
|
||||||
if( !answer || !*answer ) {
|
|
||||||
|
if ( !answer || !*answer )
|
||||||
|
{
|
||||||
xfree(answer);
|
xfree(answer);
|
||||||
break;
|
break; /* No more recipients entered - get out of loop. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do group expand here too. The trick here is to continue
|
||||||
|
the loop if any expansion occured. The code above will
|
||||||
|
then list all expanded keys. */
|
||||||
if (expand_id(answer,&backlog,0))
|
if (expand_id(answer,&backlog,0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Get and check key for the current name. */
|
||||||
if (pk)
|
if (pk)
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
@ -892,43 +954,53 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 );
|
rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 );
|
||||||
if (rc)
|
if (rc)
|
||||||
tty_printf(_("No such user ID.\n"));
|
tty_printf(_("No such user ID.\n"));
|
||||||
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
|
else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) )
|
||||||
if( have_def_rec ) {
|
{
|
||||||
if (key_present_in_pk_list(pk_list, pk) == 0) {
|
if ( have_def_rec )
|
||||||
|
{
|
||||||
|
/* No validation for a default recipient. */
|
||||||
|
if (!key_present_in_pk_list(pk_list, pk))
|
||||||
|
{
|
||||||
free_public_key (pk); pk = NULL;
|
free_public_key (pk); pk = NULL;
|
||||||
log_info (_("skipped: public key "
|
log_info (_("skipped: public key "
|
||||||
"already set as default recipient\n") );
|
"already set as default recipient\n") );
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
PK_LIST r = xmalloc (sizeof *r);
|
PK_LIST r = xmalloc (sizeof *r);
|
||||||
r->pk = pk; pk = NULL;
|
r->pk = pk; pk = NULL;
|
||||||
r->next = pk_list;
|
r->next = pk_list;
|
||||||
r->flags = 0; /* no throwing default ids */
|
r->flags = 0; /* No throwing default ids. */
|
||||||
pk_list = r;
|
pk_list = r;
|
||||||
}
|
}
|
||||||
any_recipients = 1;
|
any_recipients = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{ /* Check validity of this key. */
|
||||||
int trustlevel;
|
int trustlevel;
|
||||||
|
|
||||||
trustlevel = get_validity (pk, pk->user_id);
|
trustlevel = get_validity (pk, pk->user_id);
|
||||||
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
|
if ( (trustlevel & TRUST_FLAG_DISABLED) )
|
||||||
|
{
|
||||||
tty_printf (_("Public key is disabled.\n") );
|
tty_printf (_("Public key is disabled.\n") );
|
||||||
}
|
}
|
||||||
else if( do_we_trust_pre( pk, trustlevel ) ) {
|
else if ( do_we_trust_pre (pk, trustlevel) )
|
||||||
/* Skip the actual key if the key is already present
|
{
|
||||||
* in the list */
|
/* Skip the actual key if the key is already
|
||||||
if (key_present_in_pk_list(pk_list, pk) == 0) {
|
* present in the list */
|
||||||
|
if (!key_present_in_pk_list(pk_list, pk))
|
||||||
|
{
|
||||||
free_public_key(pk); pk = NULL;
|
free_public_key(pk); pk = NULL;
|
||||||
log_info(_("skipped: public key already set\n") );
|
log_info(_("skipped: public key already set\n") );
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
PK_LIST r;
|
PK_LIST r;
|
||||||
r = xmalloc( sizeof *r );
|
r = xmalloc( sizeof *r );
|
||||||
r->pk = pk; pk = NULL;
|
r->pk = pk; pk = NULL;
|
||||||
r->next = pk_list;
|
r->next = pk_list;
|
||||||
r->flags = 0; /* no throwing interactive ids */
|
r->flags = 0; /* No throwing interactive ids. */
|
||||||
pk_list = r;
|
pk_list = r;
|
||||||
}
|
}
|
||||||
any_recipients = 1;
|
any_recipients = 1;
|
||||||
@ -939,49 +1011,63 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
xfree(def_rec); def_rec = NULL;
|
xfree(def_rec); def_rec = NULL;
|
||||||
have_def_rec = 0;
|
have_def_rec = 0;
|
||||||
}
|
}
|
||||||
if( pk ) {
|
if ( pk )
|
||||||
|
{
|
||||||
free_public_key( pk );
|
free_public_key( pk );
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( !any_recipients && (def_rec = default_recipient()) ) {
|
else if ( !any_recipients && (def_rec = default_recipient()) )
|
||||||
|
{
|
||||||
|
/* We are in batch mode and have only a default recipient. */
|
||||||
pk = xmalloc_clear( sizeof *pk );
|
pk = xmalloc_clear( sizeof *pk );
|
||||||
pk->req_usage = use;
|
pk->req_usage = use;
|
||||||
/* The default recipient may be disabled */
|
|
||||||
|
/* The default recipient is allowed to be disabled; thus pass 1
|
||||||
|
as last argument. */
|
||||||
rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1);
|
rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 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=check_pubkey_algo2(pk->pubkey_algo, use)) ) {
|
else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) )
|
||||||
|
{
|
||||||
/* Mark any_recipients here since the default recipient
|
/* Mark any_recipients here since the default recipient
|
||||||
would have been used if it wasn't already there. It
|
would have been used if it wasn't already there. It
|
||||||
doesn't really matter if we got this key from the default
|
doesn't really matter if we got this key from the default
|
||||||
recipient or an encrypt-to. */
|
recipient or an encrypt-to. */
|
||||||
any_recipients = 1;
|
any_recipients = 1;
|
||||||
if (key_present_in_pk_list(pk_list, pk) == 0)
|
if (!key_present_in_pk_list(pk_list, pk))
|
||||||
log_info(_("skipped: public key already set as default recipient\n"));
|
log_info (_("skipped: public key already set "
|
||||||
else {
|
"as default recipient\n"));
|
||||||
|
else
|
||||||
|
{
|
||||||
PK_LIST r = xmalloc( sizeof *r );
|
PK_LIST r = xmalloc( sizeof *r );
|
||||||
r->pk = pk; pk = NULL;
|
r->pk = pk; pk = NULL;
|
||||||
r->next = pk_list;
|
r->next = pk_list;
|
||||||
r->flags = 0; /* no throwing default ids */
|
r->flags = 0; /* No throwing default ids. */
|
||||||
pk_list = r;
|
pk_list = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( pk ) {
|
if ( pk )
|
||||||
|
{
|
||||||
free_public_key( pk );
|
free_public_key( pk );
|
||||||
pk = NULL;
|
pk = NULL;
|
||||||
}
|
}
|
||||||
xfree(def_rec); def_rec = NULL;
|
xfree(def_rec); def_rec = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
|
/* General case: Check all keys. */
|
||||||
any_recipients = 0;
|
any_recipients = 0;
|
||||||
for(; remusr; remusr = remusr->next ) {
|
for (; remusr; remusr = remusr->next )
|
||||||
|
{
|
||||||
if ( (remusr->flags & 1) )
|
if ( (remusr->flags & 1) )
|
||||||
continue; /* encrypt-to keys are already handled */
|
continue; /* encrypt-to keys are already handled. */
|
||||||
|
|
||||||
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 )) )
|
||||||
|
{
|
||||||
|
/* Key not found or other error. */
|
||||||
free_public_key( pk ); pk = NULL;
|
free_public_key( pk ); pk = NULL;
|
||||||
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
|
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
|
||||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||||
@ -989,11 +1075,15 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
-1);
|
-1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) {
|
else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) )
|
||||||
|
{
|
||||||
|
/* Key found and usable. Check validity. */
|
||||||
int trustlevel;
|
int trustlevel;
|
||||||
|
|
||||||
trustlevel = get_validity (pk, pk->user_id);
|
trustlevel = get_validity (pk, pk->user_id);
|
||||||
if( (trustlevel & TRUST_FLAG_DISABLED) ) {
|
if ( (trustlevel & TRUST_FLAG_DISABLED) )
|
||||||
|
{
|
||||||
|
/*Key has been disabled. */
|
||||||
free_public_key(pk); pk = NULL;
|
free_public_key(pk); pk = NULL;
|
||||||
log_info(_("%s: skipped: public key is disabled\n"),
|
log_info(_("%s: skipped: public key is disabled\n"),
|
||||||
remusr->d);
|
remusr->d);
|
||||||
@ -1004,21 +1094,24 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
rc=G10ERR_UNU_PUBKEY;
|
rc=G10ERR_UNU_PUBKEY;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
else if( do_we_trust_pre( pk, trustlevel ) ) {
|
else if ( do_we_trust_pre( pk, trustlevel ) )
|
||||||
/* note: do_we_trust may have changed the trustlevel */
|
{
|
||||||
|
/* Note: do_we_trust may have changed the trustlevel */
|
||||||
|
|
||||||
/* We have at least one valid recipient. It doesn't matters
|
/* We have at least one valid recipient. It doesn't
|
||||||
* if this recipient is already present. */
|
* matters if this recipient is already present. */
|
||||||
any_recipients = 1;
|
any_recipients = 1;
|
||||||
|
|
||||||
/* Skip the actual key if the key is already present
|
/* Skip the actual key if the key is already present
|
||||||
* in the list */
|
* in the list */
|
||||||
if (key_present_in_pk_list(pk_list, pk) == 0) {
|
if (!key_present_in_pk_list(pk_list, pk))
|
||||||
|
{
|
||||||
free_public_key(pk); pk = NULL;
|
free_public_key(pk); pk = NULL;
|
||||||
log_info(_("%s: skipped: public key already present\n"),
|
log_info(_("%s: skipped: public key already present\n"),
|
||||||
remusr->d);
|
remusr->d);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
PK_LIST r;
|
PK_LIST r;
|
||||||
r = xmalloc( sizeof *r );
|
r = xmalloc( sizeof *r );
|
||||||
r->pk = pk; pk = NULL;
|
r->pk = pk; pk = NULL;
|
||||||
@ -1027,7 +1120,8 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
pk_list = r;
|
pk_list = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* we don't trust this pk */
|
else
|
||||||
|
{ /* We don't trust this key. */
|
||||||
free_public_key( pk ); pk = NULL;
|
free_public_key( pk ); pk = NULL;
|
||||||
write_status_text_and_buffer (STATUS_INV_RECP, "10 ",
|
write_status_text_and_buffer (STATUS_INV_RECP, "10 ",
|
||||||
remusr->d,
|
remusr->d,
|
||||||
@ -1037,7 +1131,9 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
|
/* Key found but not usable for us (e.g. sign-only key). */
|
||||||
free_public_key( pk ); pk = NULL;
|
free_public_key( pk ); pk = NULL;
|
||||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||||
remusr->d,
|
remusr->d,
|
||||||
@ -1049,7 +1145,8 @@ build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned use )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !rc && !any_recipients ) {
|
if ( !rc && !any_recipients )
|
||||||
|
{
|
||||||
log_error(_("no valid addressees\n"));
|
log_error(_("no valid addressees\n"));
|
||||||
write_status_text (STATUS_NO_RECP, "0");
|
write_status_text (STATUS_NO_RECP, "0");
|
||||||
rc = G10ERR_NO_USER_ID;
|
rc = G10ERR_NO_USER_ID;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user