1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-02 22:38:02 +02:00

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>
This commit is contained in:
Werner Koch 2019-05-07 11:08:26 +02:00
parent b5985d0ca2
commit 5388537806
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 82 additions and 25 deletions

View File

@ -1,7 +1,7 @@
/* findkey.c - Locate the secret key /* findkey.c - Locate the secret key
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2010, 2011 Free Software Foundation, Inc. * 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2014 Werner Koch * Copyright (C) 2014, 2019 Werner Koch
* *
* This file is part of GnuPG. * 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. */ /* Note: Ownership of FNAME and FP are moved to this function. */
static gpg_error_t static gpg_error_t
write_extended_private_key (char *fname, estream_t fp, int update, 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 /* Read the key identified by GRIP from the private key directory and
return it as an gcrypt S-expression object in RESULT. On failure * return it as an gcrypt S-expression object in RESULT. If R_KEYMETA
returns an error code and stores NULL at RESULT. */ * 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 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; gpg_error_t err;
char *fname; char *fname;
@ -750,6 +783,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
char first; char first;
*result = NULL; *result = NULL;
if (r_keymeta)
*r_keymeta = NULL;
bin2hex (grip, 20, hexgrip); bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key"); strcpy (hexgrip+40, ".key");
@ -788,7 +823,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
if (first != '(') if (first != '(')
{ {
/* Key is in extended format. */ /* Key is in extended format. */
nvc_t pk; nvc_t pk = NULL;
int line; int line;
err = nvc_parse_private_key (&pk, &line, fp); err = nvc_parse_private_key (&pk, &line, fp);
@ -800,12 +835,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
else else
{ {
err = nvc_get_private_key (pk, result); err = nvc_get_private_key (pk, result);
nvc_release (pk);
if (err) if (err)
log_error ("error getting private key from '%s': %s\n", log_error ("error getting private key from '%s': %s\n",
fname, gpg_strerror (err)); fname, gpg_strerror (err));
else
nvc_delete_named (pk, "Key:");
} }
if (!err && r_keymeta)
*r_keymeta = pk;
else
nvc_release (pk);
xfree (fname); xfree (fname);
return err; return err;
} }
@ -905,6 +945,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
unsigned char *buf; unsigned char *buf;
size_t len, buflen, erroff; size_t len, buflen, erroff;
gcry_sexp_t s_skey; gcry_sexp_t s_skey;
nvc_t keymeta = NULL;
*result = NULL; *result = NULL;
if (shadow_info) if (shadow_info)
@ -912,7 +953,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (r_passphrase) if (r_passphrase)
*r_passphrase = NULL; *r_passphrase = NULL;
err = read_key_file (grip, &s_skey); err = read_key_file (grip, &s_skey, &keymeta);
if (err) if (err)
{ {
if (gpg_err_code (err) == GPG_ERR_ENOENT) if (gpg_err_code (err) == GPG_ERR_ENOENT)
@ -925,7 +966,10 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
now. */ now. */
err = make_canon_sexp (s_skey, &buf, &len); err = make_canon_sexp (s_skey, &buf, &len);
if (err) if (err)
return err; {
nvc_release (keymeta);
return err;
}
switch (agent_private_key_type (buf)) 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: case PRIVATE_KEY_PROTECTED:
{ {
char *desc_text_final; 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 /* Note, that we will take the comment as a C string for
display purposes; i.e. all stuff beyond a Nul character is * display purposes; i.e. all stuff beyond a Nul character is
ignored. */ * ignored. If a "Label" entry is available in the meta data
{ * this is used instead of the s-ecpression comment. */
gcry_sexp_t comment_sexp; 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); comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
if (comment_sexp) if (comment_sexp)
comment = gcry_sexp_nth_string (comment_sexp, 1); comment_buffer = gcry_sexp_nth_string (comment_sexp, 1);
gcry_sexp_release (comment_sexp); gcry_sexp_release (comment_sexp);
} comment = comment_buffer;
}
desc_text_final = NULL; desc_text_final = NULL;
if (desc_text) if (desc_text)
err = agent_modify_description (desc_text, comment, s_skey, err = agent_modify_description (desc_text, comment, s_skey,
&desc_text_final); &desc_text_final);
gcry_free (comment); gcry_free (comment_buffer);
if (!err) if (!err)
{ {
@ -1023,6 +1077,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase); xfree (*r_passphrase);
*r_passphrase = NULL; *r_passphrase = NULL;
} }
nvc_release (keymeta);
return err; return err;
} }
@ -1039,10 +1094,12 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase); xfree (*r_passphrase);
*r_passphrase = NULL; *r_passphrase = NULL;
} }
nvc_release (keymeta);
return err; return err;
} }
*result = s_skey; *result = s_skey;
nvc_release (keymeta);
return 0; return 0;
} }
@ -1242,7 +1299,7 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
*result = NULL; *result = NULL;
err = read_key_file (grip, &s_skey); err = read_key_file (grip, &s_skey, NULL);
if (!err) if (!err)
*result = s_skey; *result = s_skey;
return err; return err;
@ -1280,7 +1337,7 @@ agent_public_key_from_file (ctrl_t ctrl,
*result = NULL; *result = NULL;
err = read_key_file (grip, &s_skey); err = read_key_file (grip, &s_skey, NULL);
if (err) if (err)
return err; return err;
@ -1425,7 +1482,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
{ {
gcry_sexp_t sexp; gcry_sexp_t sexp;
err = read_key_file (grip, &sexp); err = read_key_file (grip, &sexp, NULL);
if (err) if (err)
{ {
if (gpg_err_code (err) == GPG_ERR_ENOENT) 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; char *default_desc = NULL;
int key_type; 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) if (gpg_err_code (err) == GPG_ERR_ENOENT)
err = gpg_error (GPG_ERR_NO_SECKEY); err = gpg_error (GPG_ERR_NO_SECKEY);
if (err) if (err)

View File

@ -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 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 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 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 passphrase. It is often used instead of a comment element as present
the S-expression of the "Key" item. in the S-expression of the "Key" item.
*** OpenSSH-cert *** OpenSSH-cert
This takes a base64 encoded string wrapped so that this This takes a base64 encoded string wrapped so that this