scd:p15: Return a display S/N via Assuan.

* scd/app-p15.c (make_pin_prompt): Factor some code out to ...
(get_dispserialno): this.
(do_getattr): Use new fucntion for a $DISPSERIALNO.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-04-08 07:54:01 +02:00
parent fd79cadf7b
commit bfedc760ef
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 54 additions and 21 deletions

View File

@ -376,6 +376,7 @@ struct app_local_s
static gpg_error_t keygrip_from_prkdf (app_t app, prkdf_object_t prkdf); static gpg_error_t keygrip_from_prkdf (app_t app, prkdf_object_t prkdf);
static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf, static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf,
unsigned char **r_cert, size_t *r_certlen); unsigned char **r_cert, size_t *r_certlen);
static char *get_dispserialno (app_t app, prkdf_object_t prkdf);
static gpg_error_t do_getattr (app_t app, ctrl_t ctrl, const char *name); static gpg_error_t do_getattr (app_t app, ctrl_t ctrl, const char *name);
@ -3037,13 +3038,13 @@ static gpg_error_t
do_getattr (app_t app, ctrl_t ctrl, const char *name) do_getattr (app_t app, ctrl_t ctrl, const char *name)
{ {
gpg_error_t err; gpg_error_t err;
prkdf_object_t prkdf;
if (!strcmp (name, "$AUTHKEYID") if (!strcmp (name, "$AUTHKEYID")
|| !strcmp (name, "$ENCRKEYID") || !strcmp (name, "$ENCRKEYID")
|| !strcmp (name, "$SIGNKEYID")) || !strcmp (name, "$SIGNKEYID"))
{ {
char *buf; char *buf;
prkdf_object_t prkdf;
/* We return the ID of the first private key capable of the /* We return the ID of the first private key capable of the
* requested action. Note that we do not yet return * requested action. Note that we do not yet return
@ -3114,7 +3115,33 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
} }
xfree (buffer); xfree (buffer);
} }
else
{
/* We use the first private key object which has a serial
* number set. If none was found, we parse the first
* object and see whether this has then a serial number. */
for (prkdf = app->app_local->private_key_info; prkdf;
prkdf = prkdf->next)
if (prkdf->serial_number)
break;
if (!prkdf && app->app_local->private_key_info)
{
prkdf = app->app_local->private_key_info;
keygrip_from_prkdf (app, prkdf);
if (!prkdf->serial_number)
prkdf = NULL;
}
if (prkdf)
{
char *sn = get_dispserialno (app, prkdf);
/* Unless there is a bogus S/N in the cert we should
* have a suitable one from the cert here now. */
err = send_status_printf (ctrl, name, "%s", sn);
xfree (sn);
return err;
}
}
/* No abbreviated serial number. */
} }
else if (!strcmp (name, "MANUFACTURER")) else if (!strcmp (name, "MANUFACTURER"))
{ {
@ -3312,32 +3339,39 @@ any_control_or_space (const char *string)
} }
/* Return an allocated string to be used as prompt. Returns NULL on /* Return a malloced serial number to be shown to the user. PRKDF is
* malloc error. */ * used to get it from a certificate; PRKDF may be NULL. */
static char * static char *
make_pin_prompt (app_t app, int remaining, const char *firstline, get_dispserialno (app_t app, prkdf_object_t prkdf)
const char *common_name, const char *serial_number)
{ {
char *serial, *tmpbuf, *result; char *serial;
const char *dispsn;
/* We prefer the SerialNumber RDN from the Subject-DN but we don't /* We prefer the SerialNumber RDN from the Subject-DN but we don't
* use it if it features a percent sign (special character in pin * use it if it features a percent sign (special character in pin
* prompts) or has any control character. */ * prompts) or has any control character. */
if (serial_number && *serial_number if (prkdf && prkdf->serial_number && *prkdf->serial_number
&& !strchr (serial_number, '%') && !strchr (prkdf->serial_number, '%')
&& !any_control_or_space (serial_number)) && !any_control_or_space (prkdf->serial_number))
{ {
serial = NULL; serial = xtrystrdup (prkdf->serial_number);
dispsn = serial_number;
} }
else else
{ {
serial = app_get_serialno (app); serial = app_get_serialno (app);
if (!serial)
return NULL; /* Ooops. */
dispsn = serial;
} }
return serial;
}
/* Return an allocated string to be used as prompt. Returns NULL on
* malloc error. */
static char *
make_pin_prompt (app_t app, int remaining, const char *firstline,
prkdf_object_t prkdf)
{
char *serial, *tmpbuf, *result;
serial = get_dispserialno (app, prkdf);
/* TRANSLATORS: Put a \x1f right before a colon. This can be /* TRANSLATORS: Put a \x1f right before a colon. This can be
* used by pinentry to nicely align the names and values. Keep * used by pinentry to nicely align the names and values. Keep
@ -3347,12 +3381,12 @@ make_pin_prompt (app_t app, int remaining, const char *firstline,
"Holder\x1f: %s" "Holder\x1f: %s"
"%s"), "%s"),
"\x1e", "\x1e",
dispsn, serial,
common_name? common_name: "", prkdf->common_name? prkdf->common_name: "",
""); "");
xfree (serial);
if (!result) if (!result)
return NULL; /* Out of core. */ return NULL; /* Out of core. */
xfree (serial);
/* Append a "remaining attempts" info if needed. */ /* Append a "remaining attempts" info if needed. */
if (remaining != -1 && remaining < 3) if (remaining != -1 && remaining < 3)
@ -3439,8 +3473,7 @@ verify_pin (app_t app,
label = _("||Please enter the PIN for the standard keys."); label = _("||Please enter the PIN for the standard keys.");
{ {
char *prompt = make_pin_prompt (app, remaining, label, char *prompt = make_pin_prompt (app, remaining, label, prkdf);
prkdf->common_name, prkdf->serial_number);
if (!prompt) if (!prompt)
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
else else