summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-05-07 11:08:26 +0200
committerWerner Koch <wk@gnupg.org>2019-05-07 11:09:09 +0200
commit5388537806411c19ea84db8c4419f410be9ac616 (patch)
tree51115c552dcc0c56ae9426b17169516ba1013cd0 /agent
parentcommon: New functions nvc_delete_named and nvc_get_string. (diff)
downloadgnupg2-5388537806411c19ea84db8c4419f410be9ac616.tar.xz
gnupg2-5388537806411c19ea84db8c4419f410be9ac616.zip
agent: Allow the use of "Label:" in a key file.
* agent/findkey.c (linefeed_to_percent0A): New. (read_key_file): Add optional arg 'keymeta' and change all callers. (agent_key_from_file): Prefer "Label:" over the comment for protected keys. -- If in the extended key format an item Label: This is my key is found, "This is my key" will be displayed instead of the comment intially recorded in the s-expression. This is pretty useful for the ssh keys because often there is only the original file name recorded in the comment. If no Label is found or it is empty the S-expression comment is used. To show more than one line, the standard name-value syntax can be used, for example: Label: The Ssh key <blank line> <space>I registered on fencepost. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'agent')
-rw-r--r--agent/findkey.c103
-rw-r--r--agent/keyformat.txt4
2 files changed, 82 insertions, 25 deletions
diff --git a/agent/findkey.c b/agent/findkey.c
index 157870e17..5699a215e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -1,7 +1,7 @@
/* findkey.c - Locate the secret key
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2010, 2011 Free Software Foundation, Inc.
- * Copyright (C) 2014 Werner Koch
+ * Copyright (C) 2014, 2019 Werner Koch
*
* This file is part of GnuPG.
*
@@ -52,6 +52,36 @@ struct try_unprotect_arg_s
};
+/* Repalce all linefeeds in STRING by "%0A" and return a new malloced
+ * string. May return NULL on memory error. */
+static char *
+linefeed_to_percent0A (const char *string)
+{
+ const char *s;
+ size_t n;
+ char *buf, *p;
+
+ for (n=0, s=string; *s; s++)
+ if (*s == '\n')
+ n += 3;
+ else
+ n++;
+ p = buf = xtrymalloc (n+1);
+ if (!buf)
+ return NULL;
+ for (s=string; *s; s++)
+ if (*s == '\n')
+ {
+ memcpy (p, "%0A", 3);
+ p += 3;
+ }
+ else
+ *p++ = *s;
+ *p = 0;
+ return buf;
+}
+
+
/* Note: Ownership of FNAME and FP are moved to this function. */
static gpg_error_t
write_extended_private_key (char *fname, estream_t fp, int update,
@@ -734,10 +764,13 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
/* Read the key identified by GRIP from the private key directory and
- return it as an gcrypt S-expression object in RESULT. On failure
- returns an error code and stores NULL at RESULT. */
+ * return it as an gcrypt S-expression object in RESULT. If R_KEYMETA
+ * is not NULl and the extended key format is used, the meta data
+ * items are stored there. However the "Key:" item is removed from
+ * it. On failure returns an error code and stores NULL at RESULT and
+ * R_KEYMETA. */
static gpg_error_t
-read_key_file (const unsigned char *grip, gcry_sexp_t *result)
+read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta)
{
gpg_error_t err;
char *fname;
@@ -750,6 +783,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
char first;
*result = NULL;
+ if (r_keymeta)
+ *r_keymeta = NULL;
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
@@ -788,7 +823,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
if (first != '(')
{
/* Key is in extended format. */
- nvc_t pk;
+ nvc_t pk = NULL;
int line;
err = nvc_parse_private_key (&pk, &line, fp);
@@ -800,12 +835,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
else
{
err = nvc_get_private_key (pk, result);
- nvc_release (pk);
if (err)
log_error ("error getting private key from '%s': %s\n",
fname, gpg_strerror (err));
+ else
+ nvc_delete_named (pk, "Key:");
}
+ if (!err && r_keymeta)
+ *r_keymeta = pk;
+ else
+ nvc_release (pk);
xfree (fname);
return err;
}
@@ -905,6 +945,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
unsigned char *buf;
size_t len, buflen, erroff;
gcry_sexp_t s_skey;
+ nvc_t keymeta = NULL;
*result = NULL;
if (shadow_info)
@@ -912,7 +953,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (r_passphrase)
*r_passphrase = NULL;
- err = read_key_file (grip, &s_skey);
+ err = read_key_file (grip, &s_skey, &keymeta);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_ENOENT)
@@ -925,7 +966,10 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
now. */
err = make_canon_sexp (s_skey, &buf, &len);
if (err)
- return err;
+ {
+ nvc_release (keymeta);
+ return err;
+ }
switch (agent_private_key_type (buf))
{
@@ -950,25 +994,35 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
case PRIVATE_KEY_PROTECTED:
{
char *desc_text_final;
- char *comment = NULL;
+ char *comment_buffer = NULL;
+ const char *comment = NULL;
/* Note, that we will take the comment as a C string for
- display purposes; i.e. all stuff beyond a Nul character is
- ignored. */
- {
- gcry_sexp_t comment_sexp;
+ * display purposes; i.e. all stuff beyond a Nul character is
+ * ignored. If a "Label" entry is available in the meta data
+ * this is used instead of the s-ecpression comment. */
+ if (keymeta && (comment = nvc_get_string (keymeta, "Label:")))
+ {
+ if (strchr (comment, '\n')
+ && (comment_buffer = linefeed_to_percent0A (comment)))
+ comment = comment_buffer;
+ }
+ else
+ {
+ gcry_sexp_t comment_sexp;
- comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
- if (comment_sexp)
- comment = gcry_sexp_nth_string (comment_sexp, 1);
- gcry_sexp_release (comment_sexp);
- }
+ comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
+ if (comment_sexp)
+ comment_buffer = gcry_sexp_nth_string (comment_sexp, 1);
+ gcry_sexp_release (comment_sexp);
+ comment = comment_buffer;
+ }
desc_text_final = NULL;
if (desc_text)
err = agent_modify_description (desc_text, comment, s_skey,
&desc_text_final);
- gcry_free (comment);
+ gcry_free (comment_buffer);
if (!err)
{
@@ -1023,6 +1077,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase);
*r_passphrase = NULL;
}
+ nvc_release (keymeta);
return err;
}
@@ -1039,10 +1094,12 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase);
*r_passphrase = NULL;
}
+ nvc_release (keymeta);
return err;
}
*result = s_skey;
+ nvc_release (keymeta);
return 0;
}
@@ -1242,7 +1299,7 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
*result = NULL;
- err = read_key_file (grip, &s_skey);
+ err = read_key_file (grip, &s_skey, NULL);
if (!err)
*result = s_skey;
return err;
@@ -1280,7 +1337,7 @@ agent_public_key_from_file (ctrl_t ctrl,
*result = NULL;
- err = read_key_file (grip, &s_skey);
+ err = read_key_file (grip, &s_skey, NULL);
if (err)
return err;
@@ -1425,7 +1482,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
{
gcry_sexp_t sexp;
- err = read_key_file (grip, &sexp);
+ err = read_key_file (grip, &sexp, NULL);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_ENOENT)
@@ -1509,7 +1566,7 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
char *default_desc = NULL;
int key_type;
- err = read_key_file (grip, &s_skey);
+ err = read_key_file (grip, &s_skey, NULL);
if (gpg_err_code (err) == GPG_ERR_ENOENT)
err = gpg_error (GPG_ERR_NO_SECKEY);
if (err)
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index 058fb0143..e2ca05c84 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -90,8 +90,8 @@ so that the file can be easily inspected and edited. See section
This is a short human readable description for the key which can be
used by the software to describe the key in a user interface. For
example as part of the description in a prompt for a PIN or
-passphrase. It is often used instead of a comment element preent in
-the S-expression of the "Key" item.
+passphrase. It is often used instead of a comment element as present
+in the S-expression of the "Key" item.
*** OpenSSH-cert
This takes a base64 encoded string wrapped so that this