* findkey.c (modify_description): Keep invalid % escapes, so that

%0A may pass through.

* agent.h (server_control_s): New field USE_AUTH_CALL.
* call-scd.c (agent_card_pksign): Make use of it.
* command-ssh.c (data_sign): Set the flag.
(ssh_send_key_public): New arg OVERRIDE_COMMENT.
(card_key_available): Add new arg CARDSN.
(ssh_handler_request_identities): Use the card s/n as comment.
(sexp_key_extract): Use GCRYMPI_FMT_STD.
(data_sign): Ditto.

* learncard.c (make_shadow_info): Moved to ..
* protect.c (make_shadow_info): .. here. Return NULL on malloc
failure. Made global.
* agent.h: Add prototype.

* xasprintf.c (xtryasprintf): New.

* app-openpgp.c (get_public_key): Make sure not to return negative
numbers.
(do_sign): Allow passing of indata with algorithm prefix.
(do_auth): Allow OPENPGP.3 as an alternative ID.

* app.c (app_getattr): Return just the S/N but not the timestamp.

* no-libgcrypt.c (gcry_strdup): New.
This commit is contained in:
Werner Koch 2005-02-25 16:14:55 +00:00
parent 1f1f28555a
commit faef9f929b
18 changed files with 368 additions and 108 deletions

View File

@ -1,3 +1,22 @@
2005-02-25 Werner Koch <wk@g10code.com>
* findkey.c (modify_description): Keep invalid % escapes, so that
%0A may pass through.
* agent.h (server_control_s): New field USE_AUTH_CALL.
* call-scd.c (agent_card_pksign): Make use of it.
* command-ssh.c (data_sign): Set the flag.
(ssh_send_key_public): New arg OVERRIDE_COMMENT.
(card_key_available): Add new arg CARDSN.
(ssh_handler_request_identities): Use the card s/n as comment.
(sexp_key_extract): Use GCRYMPI_FMT_STD.
(data_sign): Ditto.
* learncard.c (make_shadow_info): Moved to ..
* protect.c (make_shadow_info): .. here. Return NULL on malloc
failure. Made global.
* agent.h: Add prototype.
2005-02-24 Werner Koch <wk@g10code.com>
* call-scd.c (unescape_status_string): New. Actual a copy of

View File

@ -116,6 +116,8 @@ struct server_control_s {
char keygrip[20];
int have_keygrip;
int use_auth_call; /* Hack to send the PKAUTH command instead of the
PKSIGN command tro scdaemon. */
};
typedef struct server_control_s *CTRL;
typedef struct server_control_s *ctrl_t;
@ -204,6 +206,7 @@ int agent_protect (const unsigned char *plainkey, const char *passphrase,
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
int agent_private_key_type (const unsigned char *privatekey);
unsigned char *make_shadow_info (const char *serialno, const char *idstring);
int agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info,
unsigned char **result);

View File

@ -225,15 +225,16 @@ start_scd (ctrl_t ctrl)
/* Tell the scdaemon that we want him to send us an event signal.
But only do this if we are running as a regular sever and not
simply as a pipe server. */
if (ctrl->connection_fd != -1)
{
#ifndef HAVE_W32_SYSTEM
char buf[100];
/* Fixme: gpg-agent does not use this signal yet. */
/* if (ctrl->connection_fd != -1) */
/* { */
/* #ifndef HAVE_W32_SYSTEM */
/* char buf[100]; */
sprintf (buf, "OPTION event-signal=%d", SIGUSR2);
assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
#endif
}
/* sprintf (buf, "OPTION event-signal=%d", SIGUSR2); */
/* assuan_transact (scd_ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); */
/* #endif */
/* } */
return 0;
}
@ -505,7 +506,8 @@ agent_card_pksign (ctrl_t ctrl,
inqparm.ctx = scd_ctx;
inqparm.getpin_cb = getpin_cb;
inqparm.getpin_cb_arg = getpin_cb_arg;
snprintf (line, DIM(line)-1, "PKSIGN %s", keyid);
snprintf (line, DIM(line)-1,
ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
line[DIM(line)-1] = 0;
rc = assuan_transact (scd_ctx, line,
membuf_data_cb, &data,
@ -518,7 +520,7 @@ agent_card_pksign (ctrl_t ctrl,
}
sigbuf = get_membuf (&data, &sigbuflen);
/* create an S-expression from it which is formatted like this:
/* Create an S-expression from it which is formatted like this:
"(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
*r_buflen = 21 + 11 + sigbuflen + 4;
*r_buf = xtrymalloc (*r_buflen);

View File

@ -659,7 +659,9 @@ open_control_file (FILE **r_fp, int append)
(i.e. where Pth might switch threads) we need to employ a
mutex. */
*r_fp = NULL;
fname = make_filename (opt.homedir, "sshcontrol.txt", NULL);
fname = make_filename (opt.homedir, "sshcontrol", NULL);
/* FIXME: With "a+" we are not able to check whether this will will
be created and thus the blurb needs to be written first. */
fp = fopen (fname, append? "a+":"r");
if (!fp && errno == ENOENT)
{
@ -1146,7 +1148,9 @@ sexp_key_extract (gcry_sexp_t sexp,
break;
}
mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG);
/* Note that we need to use STD format; i.e. prepend a 0x00 to
indicate a positive number if the high bit is set. */
mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
if (! mpi)
{
err = gpg_error (GPG_ERR_INV_SEXP);
@ -1404,9 +1408,12 @@ ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size,
}
/* Write the public key KEY_PUBLIC to STREAM in SSH key format. */
/* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
OVERRIDE_COMMENT is not NULL, it will be used instead of the
comment stored in the key. */
static gpg_error_t
ssh_send_key_public (estream_t stream, gcry_sexp_t key_public)
ssh_send_key_public (estream_t stream, gcry_sexp_t key_public,
const char *override_comment)
{
ssh_key_type_spec_t spec;
gcry_mpi_t *mpi_list;
@ -1442,7 +1449,8 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key_public)
if (err)
goto out;
err = stream_write_cstring (stream, comment);
err = stream_write_cstring (stream,
override_comment? override_comment : comment);
out:
@ -1520,17 +1528,23 @@ key_secret_to_public (gcry_sexp_t *key_public,
/* Chec whether a smartcard is available and whether it has a usable
key. Store a copy of that key at R_PK and return 0. If no key is
available store NULL at R_PK and return an error code. */
available store NULL at R_PK and return an error code. If CARDSN
is no NULL, a string with the serial number of the card will be
amalloced and stored there. */
static gpg_error_t
card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk)
card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
{
gpg_error_t err;
char *appname;
unsigned char *sbuf;
size_t sbuflen;
gcry_sexp_t pk;
char *serialno = NULL;
unsigned char *pkbuf;
size_t pkbuflen;
gcry_sexp_t s_pk;
unsigned char grip[20];
*r_pk = NULL;
if (cardsn)
*cardsn = NULL;
/* First see whether a card is available and whether the application
is supported. */
@ -1538,53 +1552,135 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk)
if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
{
/* Ask for the serial number to reset the card. */
err = agent_card_serialno (ctrl, &appname);
err = agent_card_serialno (ctrl, &serialno);
if (err)
{
if (opt.verbose)
log_info (_("can't get serial number of card: %s\n"),
log_info (_("error getting serial number of card: %s\n"),
gpg_strerror (err));
return err;
}
log_info (_("detected card with S/N: %s\n"), appname);
xfree (appname);
log_info (_("detected card with S/N: %s\n"), serialno);
err = agent_card_getattr (ctrl, "APPTYPE", &appname);
}
if (err)
{
log_error (_("error getting application type of card: %s\n"),
gpg_strerror (err));
xfree (serialno);
return err;
}
if (strcmp (appname, "OPENPGP"))
{
log_info (_("card application `%s' is not supported\n"), appname);
xfree (appname);
xfree (serialno);
return gpg_error (GPG_ERR_NOT_SUPPORTED);
}
xfree (appname);
appname = NULL;
/* Get the S/N if we don't have it yet. Use the fast getattr method. */
if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) )
{
log_error (_("error getting serial number of card: %s\n"),
gpg_strerror (err));
return err;
}
/* Read the public key. */
err = agent_card_readkey (ctrl, "OPENPGP.3", &sbuf);
err = agent_card_readkey (ctrl, "OPENPGP.3", &pkbuf);
if (err)
{
if (opt.verbose)
log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
xfree (serialno);
return err;
}
sbuflen = gcry_sexp_canon_len (sbuf, 0, NULL, NULL);
err = gcry_sexp_sscan (&pk, NULL, sbuf, sbuflen);
xfree (sbuf);
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
err = gcry_sexp_sscan (&s_pk, NULL, pkbuf, pkbuflen);
if (err)
{
log_error ("failed to build S-Exp from received card key: %s\n",
gpg_strerror (err));
xfree (pkbuf);
xfree (serialno);
return err;
}
*r_pk = pk;
if ( !gcry_pk_get_keygrip (s_pk, grip) )
{
log_debug ("error computing keygrip from received card key\n");
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
return gpg_error (GPG_ERR_INTERNAL);
}
if ( agent_key_available (grip) )
{
/* (Shadow)-key is not available in our key storage. */
unsigned char *shadow_info;
unsigned char *tmp;
shadow_info = make_shadow_info (serialno, "OPENPGP.3");
if (!shadow_info)
{
err = gpg_error_from_errno (errno);
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
return err;
}
err = agent_shadow_key (pkbuf, shadow_info, &tmp);
xfree (shadow_info);
if (err)
{
log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
return err;
}
xfree (pkbuf);
pkbuf = tmp;
pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
assert (pkbuflen);
err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
if (err)
{
log_error (_("error writing key: %s\n"), gpg_strerror (err));
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
return err;
}
}
if (cardsn)
{
size_t snlen = strlen (serialno);
if (snlen == 32
&& !memcmp (serialno, "D27600012401", 12)) /* OpenPGP card. */
*cardsn = xtryasprintf ("cardno:%.12s", serialno+16);
else /* Something is wrong: Print all. */
*cardsn = xtryasprintf ("cardno:%s", serialno);
if (!*cardsn)
{
err = gpg_error_from_errno (errno);
xfree (pkbuf);
gcry_sexp_release (s_pk);
xfree (serialno);
return err;
}
}
xfree (pkbuf);
xfree (serialno);
*r_pk = s_pk;
return 0;
}
@ -1615,6 +1711,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
gpg_error_t ret_err;
int ret;
FILE *ctrl_fp = NULL;
char *cardsn;
/* Prepare buffer stream. */
@ -1665,13 +1762,14 @@ ssh_handler_request_identities (ctrl_t ctrl,
/* First check whether a key is currently available in the card
reader - this should be allowed even without being listed in
sshcontrol.txt. */
sshcontrol. */
if (!card_key_available (ctrl, &key_public))
if (!card_key_available (ctrl, &key_public, &cardsn))
{
err = ssh_send_key_public (key_blobs, key_public);
err = ssh_send_key_public (key_blobs, key_public, cardsn);
gcry_sexp_release (key_public);
key_public = NULL;
xfree (cardsn);
if (err)
goto out;
@ -1740,7 +1838,7 @@ ssh_handler_request_identities (ctrl_t ctrl,
gcry_sexp_release (key_secret);
key_secret = NULL;
err = ssh_send_key_public (key_blobs, key_public);
err = ssh_send_key_public (key_blobs, key_public, NULL);
if (err)
goto out;
@ -1845,9 +1943,11 @@ data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
sig_value = NULL;
mpis = NULL;
ctrl->use_auth_call = 1;
err = agent_pksign_do (ctrl,
_("Please provide the passphrase "
"for the ssh key `%c':"), &signature_sexp, 0);
_("Please enter the passphrase "
"for the ssh key%0A %c"), &signature_sexp, 0);
ctrl->use_auth_call = 0;
if (err)
goto out;
@ -2189,7 +2289,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME: Why?? */
/* Check whether the key is alread in our key storage. Don't do
/* Check whether the key is already in our key storage. Don't do
anything then. */
if ( !agent_key_available (key_grip_raw) )
goto out; /* Yes, key is available. */
@ -2200,8 +2300,8 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
goto out;
if ( asprintf (&description,
_("Please enter a passphrase to protect%%0A"
"the received secret key%%0A"
_("Please enter a passphrase to protect"
" the received secret key%%0A"
" %s%%0A"
"within gpg-agent's key storage"),
comment ? comment : "?") < 0)

View File

@ -166,9 +166,7 @@ modify_description (const char *in, const char *comment, char **result)
special = 0;
for (i = 0; i < in_len; i++)
{
if (in[i] == '%')
special = 1;
else if (special)
if (special)
{
special = 0;
switch (in[i])
@ -190,10 +188,19 @@ modify_description (const char *in, const char *comment, char **result)
out_len += comment_length;
break;
default: /* Invalid special sequences are ignored. */
default: /* Invalid special sequences are kept as they are. */
if (out)
{
*out++ = '%';
*out++ = in[i];
}
else
out_len+=2;
break;
}
}
else if (in[i] == '%')
special = 1;
else
{
if (out)

View File

@ -161,9 +161,9 @@ term secret key because it can be visually be better distinguished
from the term public key.
[2] The keygrip is a unique identifier for a key pair, it is
independent of any protocol, so that the same key can be ised with
independent of any protocol, so that the same key can be used with
different protocols. PKCS-15 calls this a subjectKeyHash; it can be
calculate using Libgcrypt's gcry_pk_get_keygrip().
calculated using Libgcrypt's gcry_pk_get_keygrip ().
[3] Even when canonical representation are required we will show the
S-expression here in a more readable representation.

View File

@ -1,5 +1,5 @@
/* learncard.c - Handle the LEARN command
* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -239,32 +239,6 @@ sinfo_cb (void *opaque, const char *keyword, size_t keywordlen,
}
/* Create an S-expression with the shadow info. */
static unsigned char *
make_shadow_info (const char *serialno, const char *idstring)
{
const char *s;
unsigned char *info, *p;
char numbuf[21];
int n;
for (s=serialno, n=0; *s && s[1]; s += 2)
n++;
info = p = xtrymalloc (1 + 21 + n
+ 21 + strlen (idstring) + 1 + 1);
*p++ = '(';
sprintf (numbuf, "%d:", n);
p = stpcpy (p, numbuf);
for (s=serialno; *s && s[1]; s += 2)
*p++ = xtoi_2 (s);
sprintf (numbuf, "%d:", strlen (idstring));
p = stpcpy (p, numbuf);
p = stpcpy (p, idstring);
*p++ = ')';
*p = 0;
return info;
}
static int
send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context)

View File

@ -110,7 +110,7 @@ static ARGPARSE_OPTS opts[] = {
{ oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" },
{ oProtect, "protect", 256, "protect a private key"},
{ oUnprotect, "unprotect", 256, "unprotect a private key"},
{ oShadow, "shadow", 256, "create a shadow entry for a priblic key"},
{ oShadow, "shadow", 256, "create a shadow entry for a public key"},
{ oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
{ oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},

View File

@ -831,10 +831,43 @@ hash_passphrase (const char *passphrase, int hashalgo,
/* Create an canonical encoded S-expression with the shadow info from
a card's SERIALNO and the IDSTRING. */
unsigned char *
make_shadow_info (const char *serialno, const char *idstring)
{
const char *s;
unsigned char *info, *p;
char numbuf[21];
int n;
for (s=serialno, n=0; *s && s[1]; s += 2)
n++;
info = p = xtrymalloc (1 + 21 + n
+ 21 + strlen (idstring) + 1 + 1);
if (!info)
return NULL;
*p++ = '(';
sprintf (numbuf, "%d:", n);
p = stpcpy (p, numbuf);
for (s=serialno; *s && s[1]; s += 2)
*p++ = xtoi_2 (s);
sprintf (numbuf, "%d:", strlen (idstring));
p = stpcpy (p, numbuf);
p = stpcpy (p, idstring);
*p++ = ')';
*p = 0;
return info;
}
/* Create a shadow key from a public key. We use the shadow protocol
"ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
S-expression is returned in an allocated buffer RESULT will point
to. The input parameters are expected to be valid canonilized
to. The input parameters are expected to be valid canonicalized
S-expressions */
int
agent_shadow_key (const unsigned char *pubkey,
@ -894,7 +927,7 @@ agent_shadow_key (const unsigned char *pubkey,
s++;
assert (depth == 1);
/* calculate required length by taking in account: the "shadowed-"
/* Calculate required length by taking in account: the "shadowed-"
prefix, the "shadowed", "t1-v1" as well as some parenthesis */
n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
*result = p = xtrymalloc (n);

View File

@ -1,3 +1,7 @@
2005-02-25 Werner Koch <wk@g10code.com>
* xasprintf.c (xtryasprintf): New.
2005-01-26 Moritz Schulte <moritz@g10code.com>
* Makefile.am (libcommon_a_SOURCES): New source files: estream.c,

View File

@ -131,6 +131,10 @@ const char *default_homedir (void);
freed using xfree. This function simply dies on memory failure,
thus no extra check is required. */
char *xasprintf (const char *fmt, ...) JNLIB_GCC_A_PRINTF(1,2);
/* Same as asprintf but return an allocated buffer suitable to be
freed using xfree. This function returns NULL on memory failure and
sets errno. */
char *xtryasprintf (const char *fmt, ...) JNLIB_GCC_A_PRINTF(1,2);
const char *print_fname_stdout (const char *s);
const char *print_fname_stdin (const char *s);

View File

@ -1,5 +1,5 @@
/* xasprintf.c
* Copyright (C) 2003 Free Software Foundation, Inc.
* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -42,3 +42,21 @@ xasprintf (const char *fmt, ...)
free (buf);
return p;
}
/* Same as above bit return NULL on memory failure. */
char *
xtryasprintf (const char *fmt, ...)
{
int rc;
va_list ap;
char *buf, *p;
va_start (ap, fmt);
rc = vasprintf (&buf, fmt, ap);
va_end (ap);
if (rc < 0)
return NULL;
p = xtrystrdup (buf);
free (buf);
return p;
}

View File

@ -1,3 +1,12 @@
2005-02-25 Werner Koch <wk@g10code.com>
* app-openpgp.c (get_public_key): Make sure not to return negative
numbers.
(do_sign): Allow passing of indata with algorithm prefix.
(do_auth): Allow OPENPGP.3 as an alternative ID.
* app.c (app_getattr): Return just the S/N but not the timestamp.
2005-02-24 Werner Koch <wk@g10code.com>
* app.c (app_getattr): Return APPTYPE or SERIALNO type even if the

View File

@ -794,6 +794,8 @@ get_public_key (app_t app, int keyno)
const unsigned char *keydata, *m, *e;
size_t buflen, keydatalen, mlen, elen;
gcry_sexp_t sexp;
unsigned char *mbuf = NULL;
unsigned char *ebuf = NULL;
if (keyno < 1 || keyno > 3)
return gpg_error (GPG_ERR_INV_ID);
@ -835,6 +837,7 @@ get_public_key (app_t app, int keyno)
log_error (_("response does not contain the RSA modulus\n"));
goto leave;
}
e = find_tlv (keydata, keydatalen, 0x0082, &elen);
if (!e)
@ -844,10 +847,38 @@ get_public_key (app_t app, int keyno)
goto leave;
}
/* Prepend numbers with a 0 if needed. */
if (mlen && (*m & 0x80))
{
mbuf = xtrymalloc ( mlen + 1);
if (!mbuf)
{
err = gpg_error_from_errno (errno);
goto leave;
}
*mbuf = 0;
memcpy (mbuf+1, m, mlen);
mlen++;
m = mbuf;
}
if (elen && (*e & 0x80))
{
ebuf = xtrymalloc ( elen + 1);
if (!ebuf)
{
err = gpg_error_from_errno (errno);
goto leave;
}
*ebuf = 0;
memcpy (ebuf+1, e, elen);
elen++;
e = ebuf;
}
err = gcry_sexp_build (&sexp, NULL,
"(public-key (rsa (n %b) (e %b)))",
(int)mlen, m,(int)elen, e);
if (err)
{
log_error ("error formatting the key into an S-expression: %s\n",
@ -874,6 +905,8 @@ get_public_key (app_t app, int keyno)
app->app_local->pk[keyno].read_done = 1;
xfree (buffer);
xfree (mbuf);
xfree (ebuf);
return 0;
}
#endif /* GNUPG_MAJOR_VERSION > 1 */
@ -1557,7 +1590,15 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE);
if (indatalen != 20)
if (indatalen == 20)
;
else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_SHA1
&& !memcmp (indata, sha1_prefix, 15))
;
else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_RMD160
&& !memcmp (indata, rmd160_prefix, 15))
;
else
return gpg_error (GPG_ERR_INV_VALUE);
/* Check whether an OpenPGP card of any version has been requested. */
@ -1668,7 +1709,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
/* Compute a digital signature using the INTERNAL AUTHENTICATE command
on INDATA which is expected to be the raw message digest. For this
application the KEYIDSTR consists of the serialnumber and the
fingerprint delimited by a slash.
fingerprint delimited by a slash. Optionally the id OPENPGP.3 may
be given.
Note that this fucntion may return the error code
GPG_ERR_WRONG_CARD to indicate that the card currently present does
@ -1693,27 +1735,31 @@ do_auth (app_t app, const char *keyidstr,
return gpg_error (GPG_ERR_INV_VALUE);
/* Check whether an OpenPGP card of any version has been requested. */
if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
return gpg_error (GPG_ERR_INV_ID);
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
if (!strcmp (keyidstr, "OPENPGP.3"))
;
if (n != 32)
else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
return gpg_error (GPG_ERR_INV_ID);
else if (!*s)
; /* no fingerprint given: we allow this for now. */
else if (*s == '/')
fpr = s + 1;
else
return gpg_error (GPG_ERR_INV_ID);
{
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
;
if (n != 32)
return gpg_error (GPG_ERR_INV_ID);
else if (!*s)
; /* no fingerprint given: we allow this for now. */
else if (*s == '/')
fpr = s + 1;
else
return gpg_error (GPG_ERR_INV_ID);
for (s=keyidstr, n=0; n < 16; s += 2, n++)
tmp_sn[n] = xtoi_2 (s);
if (app->serialnolen != 16)
return gpg_error (GPG_ERR_INV_CARD);
if (memcmp (app->serialno, tmp_sn, 16))
return gpg_error (GPG_ERR_WRONG_CARD);
for (s=keyidstr, n=0; n < 16; s += 2, n++)
tmp_sn[n] = xtoi_2 (s);
if (app->serialnolen != 16)
return gpg_error (GPG_ERR_INV_CARD);
if (memcmp (app->serialno, tmp_sn, 16))
return gpg_error (GPG_ERR_WRONG_CARD);
}
/* If a fingerprint has been specified check it against the one on
the card. This is allows for a meaningful error message in case

View File

@ -314,7 +314,6 @@ app_getattr (APP app, CTRL ctrl, const char *name)
}
if (name && !strcmp (name, "SERIALNO"))
{
char *serial_and_stamp;
char *serial;
time_t stamp;
int rc;
@ -322,15 +321,8 @@ app_getattr (APP app, CTRL ctrl, const char *name)
rc = app_get_serial_and_stamp (app, &serial, &stamp);
if (rc)
return rc;
rc = asprintf (&serial_and_stamp, "%s %lu",
serial, (unsigned long)stamp);
rc = (rc < 0)? gpg_error_from_errno (errno) : 0;
send_status_info (ctrl, "SERIALNO", serial, strlen (serial), NULL, 0);
xfree (serial);
if (rc)
return rc;
send_status_info (ctrl, "SERIALNO",
serial_and_stamp, strlen (serial_and_stamp), NULL, 0);
free (serial_and_stamp);
return 0;
}

View File

@ -1,3 +1,7 @@
2005-02-25 Werner Koch <wk@g10code.com>
* no-libgcrypt.c (gcry_strdup): New.
2005-02-24 Werner Koch <wk@g10code.com>
* gpg-connect-agent.c: New.

View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <assuan.h>
#include "i18n.h"
@ -40,7 +41,8 @@ enum cmd_and_opt_values
oVerbose = 'v',
oNoVerbose = 500,
oHomedir
oHomedir,
oHex
};
@ -52,6 +54,7 @@ static ARGPARSE_OPTS opts[] =
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("quiet") },
{ oHex, "hex", 0, N_("print data out hex encoded") },
/* hidden options */
{ oNoVerbose, "no-verbose", 0, "@"},
@ -66,7 +69,7 @@ struct
int verbose; /* Verbosity level. */
int quiet; /* Be extra quiet. */
const char *homedir; /* Configuration directory name */
int hex; /* Print data lines in hex format. */
} opt;
@ -155,6 +158,7 @@ main (int argc, char **argv)
case oVerbose: opt.verbose++; break;
case oNoVerbose: opt.verbose = 0; break;
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oHex: opt.hex = 1; break;
default: pargs.err = 2; break;
}
@ -220,6 +224,7 @@ read_and_print_response (assuan_context_t ctx)
char *line;
int linelen;
assuan_error_t rc;
int i, j;
for (;;)
{
@ -234,8 +239,42 @@ read_and_print_response (assuan_context_t ctx)
if (linelen >= 1
&& line[0] == 'D' && line[1] == ' ')
{
fwrite (line, linelen, 1, stdout);
putchar ('\n');
if (opt.hex)
{
for (i=2; i < linelen; )
{
int save_i = i;
printf ("D[%04X] ", i-2);
for (j=0; j < 16 ; j++, i++)
{
if (j == 8)
putchar (' ');
if (i < linelen)
printf (" %02X", ((unsigned char*)line)[i]);
else
fputs (" ", stdout);
}
fputs (" ", stdout);
i= save_i;
for (j=0; j < 16; j++, i++)
{
unsigned int c = ((unsigned char*)line)[i];
if ( i >= linelen )
putchar (' ');
else if (isascii (c) && isprint (c) && !iscntrl (c))
putchar (c);
else
putchar ('.');
}
putchar ('\n');
}
}
else
{
fwrite (line, linelen, 1, stdout);
putchar ('\n');
}
}
else if (linelen >= 1
&& line[0] == 'S'

View File

@ -53,6 +53,12 @@ gcry_xmalloc (size_t n)
return p;
}
char *
gcry_strdup (const char *string)
{
return malloc (strlen (string)+1);
}
void *
gcry_realloc (void *a, size_t n)