aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2023-11-21 07:34:04 +0000
committerWerner Koch <[email protected]>2023-11-21 07:37:41 +0000
commitcf2d3f7ba0b7ffd0f1c014186fb60630c132dba1 (patch)
treeab35e6ce0810bfdb0e881ef7ac67f8cd020ac99f
parentscd: New option --debug-allow-pin-logging. (diff)
downloadgnupg-cf2d3f7ba0b7ffd0f1c014186fb60630c132dba1.tar.gz
gnupg-cf2d3f7ba0b7ffd0f1c014186fb60630c132dba1.zip
agent: Update the key file only if not changed.
* common/name-value.c (struct name_value_container): Add flag "modified". (nvc_modified): New. (nvc_new): Set flag. (_nvc_add): Set flag. (nvc_delete): Set flag. (nvc_set): Set flag unless value did not change. (nve_set): Add arg PK. Change the caller. * agent/findkey.c (agent_write_private_key): Update only if modified. -- This helps software which uses a file system watcher to track changes to private keys. In particular smartcard triggered changes are a problem for such software because this may at worst trigger another smartcard read. GnuPG-bug-id: 6829
-rw-r--r--agent/findkey.c11
-rw-r--r--common/name-value.c47
-rw-r--r--common/name-value.h7
3 files changed, 56 insertions, 9 deletions
diff --git a/agent/findkey.c b/agent/findkey.c
index a5f022574..9e5550225 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -146,6 +146,8 @@ agent_write_private_key (const unsigned char *grip,
}
}
+ nvc_modified (pk, 1); /* Clear that flag after a read. */
+
if (!pk)
{
/* Key is still in the old format or does not exist - create a
@@ -242,7 +244,7 @@ agent_write_private_key (const unsigned char *grip,
; /* No need to update Token entry. */
else
{
- err = nve_set (item, token);
+ err = nve_set (pk, item, token);
if (err)
goto leave;
}
@@ -263,6 +265,13 @@ agent_write_private_key (const unsigned char *grip,
goto leave;
}
+ /* Check whether we need to write the file at all. */
+ if (!nvc_modified (pk, 0))
+ {
+ err = 0;
+ goto leave;
+ }
+
/* Create a temporary file for writing. */
tmpfname = fname_from_keygrip (grip, 1);
fp = tmpfname ? es_fopen (tmpfname, "wbx,mode=-rw") : NULL;
diff --git a/common/name-value.c b/common/name-value.c
index 0dffc63b4..b7bc32844 100644
--- a/common/name-value.c
+++ b/common/name-value.c
@@ -48,6 +48,7 @@ struct name_value_container
struct name_value_entry *first;
struct name_value_entry *last;
unsigned int private_key_mode:1;
+ unsigned int modified:1;
};
@@ -87,11 +88,15 @@ my_error (gpg_err_code_t ec)
/* Allocation and deallocation. */
-/* Allocate a private key container structure. */
+/* Allocate a name value container structure. */
nvc_t
nvc_new (void)
{
- return xtrycalloc (1, sizeof (struct name_value_container));
+ nvc_t nvc;
+ nvc = xtrycalloc (1, sizeof (struct name_value_container));
+ if (nvc)
+ nvc->modified = 1;
+ return nvc;
}
@@ -142,6 +147,24 @@ nvc_release (nvc_t pk)
xfree (pk);
}
+
+/* Return the modified-flag of the container and clear it if CLEAR is
+ * set. That flag is set for a new container and set with each
+ * update. */
+int
+nvc_modified (nvc_t pk, int clear)
+{
+ int modified;
+
+ if (!pk)
+ return 0;
+ modified = pk->modified;
+ if (clear)
+ pk->modified = 0;
+ return modified;
+}
+
+
/* Dealing with names and values. */
@@ -427,6 +450,8 @@ _nvc_add (nvc_t pk, char *name, char *value, strlist_t raw_value,
else
pk->first = pk->last = e;
+ pk->modified = 1;
+
leave:
if (err)
{
@@ -470,6 +495,7 @@ gpg_error_t
nvc_set (nvc_t pk, const char *name, const char *value)
{
nve_t e;
+ char *v;
if (! valid_name (name))
return GPG_ERR_INV_NAME;
@@ -477,7 +503,12 @@ nvc_set (nvc_t pk, const char *name, const char *value)
e = nvc_lookup (pk, name);
if (e)
{
- char *v;
+ if (e->value && value && !strcmp (e->value, value))
+ {
+ /* Setting same value - ignore this call and don't set the
+ * modified flag. */
+ return 0;
+ }
v = xtrystrdup (value);
if (v == NULL)
@@ -489,7 +520,7 @@ nvc_set (nvc_t pk, const char *name, const char *value)
wipememory (e->value, strlen (e->value));
xfree (e->value);
e->value = v;
-
+ pk->modified = 1;
return 0;
}
else
@@ -497,9 +528,10 @@ nvc_set (nvc_t pk, const char *name, const char *value)
}
-/* Update entry E to VALUE. */
+/* Update entry E to VALUE. PK is optional; if given its modified
+ * flag will be updated. */
gpg_error_t
-nve_set (nve_t e, const char *value)
+nve_set (nvc_t pk, nve_t e, const char *value)
{
char *v;
@@ -516,6 +548,8 @@ nve_set (nve_t e, const char *value)
wipememory (e->value, strlen (e->value));
xfree (e->value);
e->value = v;
+ if (pk)
+ pk->modified = 1;
return 0;
}
@@ -536,6 +570,7 @@ nvc_delete (nvc_t pk, nve_t entry)
pk->last = entry->prev;
nve_release (entry, pk->private_key_mode);
+ pk->modified = 1;
}
diff --git a/common/name-value.h b/common/name-value.h
index b3fc2f63c..dfded6678 100644
--- a/common/name-value.h
+++ b/common/name-value.h
@@ -50,6 +50,9 @@ nvc_t nvc_new_private_key (void);
/* Release a name value container structure. */
void nvc_release (nvc_t pk);
+/* Return the modified flag and optionally clear it. */
+int nvc_modified (nvc_t pk, int clear);
+
/* Get the name. */
char *nve_name (nve_t pke);
@@ -92,8 +95,8 @@ gpg_error_t nvc_add (nvc_t pk, const char *name, const char *value);
first entry is updated. */
gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value);
-/* Update entry E to VALUE. */
-gpg_error_t nve_set (nve_t e, const char *value);
+/* Update entry E to VALUE. PK is optional. */
+gpg_error_t nve_set (nvc_t pk, nve_t e, const char *value);
/* Delete the given entry from PK. */
void nvc_delete (nvc_t pk, nve_t pke);