mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
Changed signature status cache
This commit is contained in:
parent
a3af543617
commit
1f4bdf4d26
18 changed files with 478 additions and 281 deletions
449
g10/keyring.c
449
g10/keyring.c
|
@ -32,6 +32,7 @@
|
|||
#include "packet.h"
|
||||
#include "keydb.h"
|
||||
#include "options.h"
|
||||
#include "main.h" /*for check_key_signature()*/
|
||||
#include "i18n.h"
|
||||
|
||||
typedef struct keyring_name *KR_NAME;
|
||||
|
@ -219,7 +220,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||
{
|
||||
PACKET *pkt;
|
||||
int rc;
|
||||
KBNODE keyblock = NULL, node;
|
||||
KBNODE keyblock = NULL, node, lastnode;
|
||||
IOBUF a;
|
||||
int in_cert = 0;
|
||||
int pk_no = 0;
|
||||
|
@ -246,6 +247,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||
pkt = m_alloc (sizeof *pkt);
|
||||
init_packet (pkt);
|
||||
hd->found.n_packets = 0;;
|
||||
lastnode = NULL;
|
||||
while ((rc=parse_packet (a, pkt)) != -1) {
|
||||
hd->found.n_packets++;
|
||||
if (rc == G10ERR_UNKNOWN_PACKET) {
|
||||
|
@ -273,36 +275,64 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||
}
|
||||
|
||||
in_cert = 1;
|
||||
node = new_kbnode (pkt);
|
||||
if (!keyblock)
|
||||
keyblock = node;
|
||||
else
|
||||
add_kbnode (keyblock, node);
|
||||
|
||||
if ( pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| pkt->pkttype == PKT_PUBLIC_SUBKEY
|
||||
|| pkt->pkttype == PKT_SECRET_KEY
|
||||
|| pkt->pkttype == PKT_SECRET_SUBKEY) {
|
||||
if (++pk_no == hd->found.pk_no)
|
||||
node->flag |= 1;
|
||||
if (pkt->pkttype == PKT_RING_TRUST) {
|
||||
/*(this code is duplicated after the loop)*/
|
||||
if ( lastnode
|
||||
&& lastnode->pkt->pkttype == PKT_SIGNATURE
|
||||
&& (pkt->pkt.ring_trust->sigcache & 1) ) {
|
||||
/* this is a ring trust packet with a checked signature
|
||||
* status cache following directly a signature paket.
|
||||
* Set the cache status into that signature packet */
|
||||
PKT_signature *sig = lastnode->pkt->pkt.signature;
|
||||
|
||||
sig->flags.checked = 1;
|
||||
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
|
||||
}
|
||||
/* reset lastnode, so that we set the cache status only from
|
||||
* the ring trust packet immediately folling a signature */
|
||||
lastnode = NULL;
|
||||
}
|
||||
else if ( pkt->pkttype == PKT_USER_ID) {
|
||||
if (++uid_no == hd->found.uid_no)
|
||||
node->flag |= 2;
|
||||
else {
|
||||
node = lastnode = new_kbnode (pkt);
|
||||
if (!keyblock)
|
||||
keyblock = node;
|
||||
else
|
||||
add_kbnode (keyblock, node);
|
||||
|
||||
if ( pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| pkt->pkttype == PKT_PUBLIC_SUBKEY
|
||||
|| pkt->pkttype == PKT_SECRET_KEY
|
||||
|| pkt->pkttype == PKT_SECRET_SUBKEY) {
|
||||
if (++pk_no == hd->found.pk_no)
|
||||
node->flag |= 1;
|
||||
}
|
||||
else if ( pkt->pkttype == PKT_USER_ID) {
|
||||
if (++uid_no == hd->found.uid_no)
|
||||
node->flag |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
pkt = m_alloc (sizeof *pkt);
|
||||
init_packet(pkt);
|
||||
}
|
||||
|
||||
if (rc == -1 && keyblock)
|
||||
if (rc == -1 && keyblock)
|
||||
rc = 0; /* got the entire keyblock */
|
||||
|
||||
if (rc || !ret_kb)
|
||||
release_kbnode (keyblock);
|
||||
else
|
||||
else {
|
||||
/*(duplicated form the loop body)*/
|
||||
if ( pkt && pkt->pkttype == PKT_RING_TRUST
|
||||
&& lastnode
|
||||
&& lastnode->pkt->pkttype == PKT_SIGNATURE
|
||||
&& (pkt->pkt.ring_trust->sigcache & 1) ) {
|
||||
PKT_signature *sig = lastnode->pkt->pkt.signature;
|
||||
sig->flags.checked = 1;
|
||||
sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
|
||||
}
|
||||
*ret_kb = keyblock;
|
||||
|
||||
}
|
||||
free_packet (pkt);
|
||||
m_free (pkt);
|
||||
iobuf_close(a);
|
||||
|
@ -874,6 +904,285 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc)
|
|||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
create_tmp_file (const char *template,
|
||||
char **r_bakfname, char **r_tmpfname, IOBUF *r_fp)
|
||||
{
|
||||
char *bakfname, *tmpfname;
|
||||
|
||||
*r_bakfname = NULL;
|
||||
*r_tmpfname = NULL;
|
||||
|
||||
# ifdef USE_ONLY_8DOT3
|
||||
/* Here is another Windoze bug?:
|
||||
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
|
||||
* but rename("pubring.gpg.tmp", "pubring.aaa");
|
||||
* works. So we replace .gpg by .bak or .tmp
|
||||
*/
|
||||
if (strlen (template) > 4
|
||||
&& !strcmp (template+strlen(template)-4, EXTSEP_S "gpg") )
|
||||
{
|
||||
bakfname = m_alloc (strlen (template) + 1);
|
||||
strcpy (bakfname, template);
|
||||
strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak");
|
||||
|
||||
tmpfname = m_alloc (strlen( template ) + 1 );
|
||||
strcpy (tmpfname,template);
|
||||
strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp");
|
||||
}
|
||||
else
|
||||
{ /* file does not end with gpg; hmmm */
|
||||
bakfname = m_alloc (strlen( template ) + 5);
|
||||
strcpy (stpcpy(bakfname, template), EXTSEP_S "bak");
|
||||
|
||||
tmpfname = m_alloc (strlen( template ) + 5);
|
||||
strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp");
|
||||
}
|
||||
# else /* Posix file names */
|
||||
bakfname = m_alloc (strlen( template ) + 2);
|
||||
strcpy (stpcpy (bakfname,template),"~");
|
||||
|
||||
tmpfname = m_alloc (strlen( template ) + 5);
|
||||
strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp");
|
||||
# endif /* Posix filename */
|
||||
|
||||
*r_fp = iobuf_create (tmpfname);
|
||||
if (!*r_fp) {
|
||||
log_error ("can't create `%s': %s\n", tmpfname, strerror(errno) );
|
||||
m_free (tmpfname);
|
||||
m_free (bakfname);
|
||||
return G10ERR_OPEN_FILE;
|
||||
}
|
||||
|
||||
*r_bakfname = bakfname;
|
||||
*r_tmpfname = tmpfname;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
rename_tmp_file (const char *bakfname, const char *tmpfname,
|
||||
const char *fname, int secret )
|
||||
{
|
||||
int rc=0;
|
||||
|
||||
/* restrict the permissions for secret keyrings */
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if (secret && !opt.preserve_permissions)
|
||||
{
|
||||
if (chmod (tmpfname, S_IRUSR | S_IWUSR) )
|
||||
{
|
||||
log_error ("chmod of `%s' failed: %s\n",
|
||||
tmpfname, strerror(errno) );
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* invalidate close caches*/
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)bakfname );
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)fname );
|
||||
|
||||
/* first make a backup file except for secret keyrings */
|
||||
if (!secret)
|
||||
{
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove (bakfname);
|
||||
#endif
|
||||
if (rename (fname, bakfname) )
|
||||
{
|
||||
log_error ("renaming `%s' to `%s' failed: %s\n",
|
||||
fname, bakfname, strerror(errno) );
|
||||
return G10ERR_RENAME_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
/* then rename the file */
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove( fname );
|
||||
#endif
|
||||
if (rename (tmpfname, fname) )
|
||||
{
|
||||
log_error ("renaming `%s' to `%s' failed: %s\n",
|
||||
tmpfname, fname, strerror(errno) );
|
||||
rc = G10ERR_RENAME_FILE;
|
||||
if (secret)
|
||||
{
|
||||
log_info(_("WARNING: 2 files with confidential"
|
||||
" information exists.\n"));
|
||||
log_info(_("%s is the unchanged one\n"), fname );
|
||||
log_info(_("%s is the new one\n"), tmpfname );
|
||||
log_info(_("Please fix this possible security flaw\n"));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_keyblock (IOBUF fp, KBNODE keyblock)
|
||||
{
|
||||
KBNODE kbctx = NULL, node;
|
||||
int rc;
|
||||
|
||||
while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
||||
continue; /* we write it later on our own */
|
||||
|
||||
if ( (rc = build_packet (fp, node->pkt) ))
|
||||
{
|
||||
log_error ("build_packet(%d) failed: %s\n",
|
||||
node->pkt->pkttype, g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if (node->pkt->pkttype == PKT_SIGNATURE)
|
||||
{ /* always write a signature cache packet */
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
unsigned int cacheval = 0;
|
||||
|
||||
if (sig->flags.checked)
|
||||
{
|
||||
cacheval |= 1;
|
||||
if (sig->flags.valid)
|
||||
cacheval |= 2;
|
||||
}
|
||||
iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
|
||||
iobuf_put (fp, 2); /* 2 bytes */
|
||||
iobuf_put (fp, 0); /* unused */
|
||||
if (iobuf_put (fp, cacheval)) {
|
||||
log_error ("writing sigcache packet failed\n");
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk over all public keyrings, check the signatures and replace the
|
||||
* keyring with a new one where the signature cache is then updated.
|
||||
* This is only done for the public keyrings.
|
||||
*/
|
||||
int
|
||||
keyring_rebuild_cache ()
|
||||
{
|
||||
KEYRING_HANDLE hd;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
KBNODE keyblock = NULL, node;
|
||||
const char *lastresname = NULL, *resname;
|
||||
IOBUF tmpfp = NULL;
|
||||
char *tmpfilename = NULL;
|
||||
char *bakfilename = NULL;
|
||||
int rc;
|
||||
ulong count = 0, sigcount = 0;
|
||||
|
||||
hd = keyring_new (0);
|
||||
memset (&desc, 0, sizeof desc);
|
||||
desc.mode = KEYDB_SEARCH_MODE_FIRST;
|
||||
|
||||
while ( !(rc = keyring_search (hd, &desc, 1)) )
|
||||
{
|
||||
desc.mode = KEYDB_SEARCH_MODE_NEXT;
|
||||
resname = keyring_get_resource_name (hd);
|
||||
if (lastresname != resname )
|
||||
{ /* we have switched to a new keyring - commit changes */
|
||||
if (tmpfp)
|
||||
{
|
||||
if (iobuf_close (tmpfp))
|
||||
{
|
||||
log_error ("error closing `%s': %s\n",
|
||||
tmpfilename, strerror (errno));
|
||||
rc = G10ERR_CLOSE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
/* because we have switched resources, we can be sure that
|
||||
* the original file is closed */
|
||||
tmpfp = NULL;
|
||||
}
|
||||
rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
|
||||
lastresname, 0) : 0;
|
||||
m_free (tmpfilename); tmpfilename = NULL;
|
||||
m_free (bakfilename); bakfilename = NULL;
|
||||
if (rc)
|
||||
goto leave;
|
||||
lastresname = resname;
|
||||
if (!opt.quiet)
|
||||
log_info (_("checking keyring `%s'\n"), resname);
|
||||
rc = create_tmp_file (resname, &bakfilename, &tmpfilename, &tmpfp);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
release_kbnode (keyblock);
|
||||
rc = keyring_get_keyblock (hd, &keyblock);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("keyring_get_keyblock failed: %s\n", g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
|
||||
|
||||
/* check all signature to set the signature's cache flags */
|
||||
for (node=keyblock; node; node=node->next)
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_SIGNATURE)
|
||||
{
|
||||
check_key_signature (keyblock, node, NULL);
|
||||
sigcount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the keyblock to the temporary file */
|
||||
rc = write_keyblock (tmpfp, keyblock);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
if ( !(++count % 50) && !opt.quiet)
|
||||
log_info(_("%lu keys so far checked (%lu signatures)\n"),
|
||||
count, sigcount );
|
||||
|
||||
} /* end main loop */
|
||||
if (rc == -1)
|
||||
rc = 0;
|
||||
if (rc)
|
||||
{
|
||||
log_error ("keyring_search failed: %s\n", g10_errstr(rc));
|
||||
goto leave;
|
||||
}
|
||||
log_info(_("%lu keys checked (%lu signatures)\n"), count, sigcount );
|
||||
if (tmpfp)
|
||||
{
|
||||
if (iobuf_close (tmpfp))
|
||||
{
|
||||
log_error ("error closing `%s': %s\n",
|
||||
tmpfilename, strerror (errno));
|
||||
rc = G10ERR_CLOSE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
/* because we have switched resources, we can be sure that
|
||||
* the original file is closed */
|
||||
tmpfp = NULL;
|
||||
}
|
||||
rc = lastresname? rename_tmp_file (bakfilename, tmpfilename,
|
||||
lastresname, 0) : 0;
|
||||
m_free (tmpfilename); tmpfilename = NULL;
|
||||
m_free (bakfilename); bakfilename = NULL;
|
||||
|
||||
leave:
|
||||
if (tmpfp)
|
||||
iobuf_cancel (tmpfp);
|
||||
m_free (tmpfilename);
|
||||
m_free (bakfilename);
|
||||
release_kbnode (keyblock);
|
||||
keyring_release (hd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Perform insert/delete/update operation.
|
||||
|
@ -932,38 +1241,9 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||
}
|
||||
|
||||
/* create the new file */
|
||||
#ifdef USE_ONLY_8DOT3
|
||||
/* Here is another Windoze bug?:
|
||||
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
|
||||
* but rename("pubring.gpg.tmp", "pubring.aaa");
|
||||
* works. So we replace .gpg by .bak or .tmp
|
||||
*/
|
||||
if( strlen (fname) > 4
|
||||
&& !strcmp (fname+strlen(fname)-4, EXTSEP_S "gpg") ) {
|
||||
bakfname = m_alloc( strlen (fname) + 1 );
|
||||
strcpy(bakfname, fname);
|
||||
strcpy(bakfname+strlen(fname)-4, EXTSEP_S "bak");
|
||||
tmpfname = m_alloc( strlen( fname ) + 1 );
|
||||
strcpy(tmpfname,fname);
|
||||
strcpy(tmpfname+strlen(fname)-4, EXTSEP_S "tmp");
|
||||
}
|
||||
else { /* file does not end with gpg; hmmm */
|
||||
bakfname = m_alloc( strlen( fname ) + 5 );
|
||||
strcpy(stpcpy(bakfname, fname), EXTSEP_S "bak");
|
||||
tmpfname = m_alloc( strlen( fname ) + 5 );
|
||||
strcpy(stpcpy(tmpfname, fname), EXTSEP_S "tmp");
|
||||
}
|
||||
#else
|
||||
bakfname = m_alloc( strlen( fname ) + 2 );
|
||||
strcpy(stpcpy(bakfname,fname),"~");
|
||||
tmpfname = m_alloc( strlen( fname ) + 5 );
|
||||
strcpy(stpcpy(tmpfname,fname), EXTSEP_S "tmp");
|
||||
#endif
|
||||
newfp = iobuf_create (tmpfname);
|
||||
if (!newfp) {
|
||||
log_error ("%s: can't create: %s\n", tmpfname, strerror(errno) );
|
||||
rc = create_tmp_file (fname, &bakfname, &tmpfname, &newfp);
|
||||
if (rc) {
|
||||
iobuf_close(fp);
|
||||
rc = G10ERR_OPEN_FILE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
@ -1003,20 +1283,12 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||
}
|
||||
|
||||
if( mode == 1 || mode == 3 ) { /* insert or update */
|
||||
KBNODE kbctx, node;
|
||||
|
||||
/* append the new data */
|
||||
kbctx=NULL;
|
||||
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
|
||||
if( (rc = build_packet( newfp, node->pkt )) ) {
|
||||
log_error("build_packet(%d) failed: %s\n",
|
||||
node->pkt->pkttype, g10_errstr(rc) );
|
||||
iobuf_close(fp);
|
||||
iobuf_cancel(newfp);
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
rc = write_keyblock (newfp, root);
|
||||
if (rc) {
|
||||
iobuf_close(fp);
|
||||
iobuf_cancel(newfp);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
if( mode == 2 || mode == 3 ) { /* delete or update */
|
||||
|
@ -1043,58 +1315,11 @@ do_copy (int mode, const char *fname, KBNODE root, int secret,
|
|||
rc = G10ERR_CLOSE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
/* if the new file is a secring, restrict the permissions */
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if( secret && !opt.preserve_permissions ) {
|
||||
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
|
||||
log_error("%s: chmod failed: %s\n",
|
||||
tmpfname, strerror(errno) );
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* rename and make backup file */
|
||||
if( !secret ) { /* but not for secret keyrings */
|
||||
iobuf_ioctl (NULL, 2, 0, (char *)bakfname );
|
||||
iobuf_ioctl (NULL, 2, 0, (char *)fname );
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove( bakfname );
|
||||
#endif
|
||||
if( rename( fname, bakfname ) ) {
|
||||
log_error("%s: rename to `%s' failed: %s\n",
|
||||
fname, bakfname, strerror(errno) );
|
||||
rc = G10ERR_RENAME_FILE;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)tmpfname );
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)fname );
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
|
||||
remove( fname );
|
||||
#endif
|
||||
if( rename( tmpfname, fname ) ) {
|
||||
log_error("%s: rename to `%s' failed: %s\n",
|
||||
tmpfname, fname,strerror(errno) );
|
||||
rc = G10ERR_RENAME_FILE;
|
||||
if( secret ) {
|
||||
log_info(_(
|
||||
"WARNING: 2 files with confidential information exists.\n"));
|
||||
log_info(_("%s is the unchanged one\n"), fname );
|
||||
log_info(_("%s is the new one\n"), tmpfname );
|
||||
log_info(_("Please fix this possible security flaw\n"));
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
rc = rename_tmp_file (bakfname, tmpfname, fname, secret);
|
||||
|
||||
leave:
|
||||
m_free(bakfname);
|
||||
m_free(tmpfname);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue