summaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2008-09-23 11:57:45 +0200
committerWerner Koch <wk@gnupg.org>2008-09-23 11:57:45 +0200
commitf899b9683b7123b7bacd5de91fb49fd2412b9116 (patch)
treeb6b89477ec7016c1d9902442db6a98e980d49a5f /g10
parent* keyserver.c (keyserver_import_cert): Allow keyserver URLs in (diff)
downloadgnupg2-f899b9683b7123b7bacd5de91fb49fd2412b9116.tar.xz
gnupg2-f899b9683b7123b7bacd5de91fb49fd2412b9116.zip
Support the Certifciate DO of the v2 OpenPGP cards.
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog11
-rw-r--r--g10/call-agent.c57
-rw-r--r--g10/call-agent.h4
-rw-r--r--g10/card-util.c172
4 files changed, 190 insertions, 54 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 3478257d5..12630794d 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,14 @@
+2008-09-16 Werner Koch <wk@g10code.com>
+
+ * card-util.c (fpr_is_ff): New.
+ (card_status): Do not print general key info for an all-ff fpr.
+ (change_login, change_private_do): Factor common code out to ...
+ (get_data_from_file): .. new.
+ (change_cert): New.
+ (card_edit): Add command "writecert".
+ * call-agent.c (writecert_parm_s): New.
+ (inq_writecert_parms, agent_scd_writecert): New.
+
2008-09-04 David Shaw <dshaw@jabberwocky.com>
* keyserver.c (keyserver_import_cert): Allow keyserver URLs in
diff --git a/g10/call-agent.c b/g10/call-agent.c
index fa68e6149..9767f040f 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -53,6 +53,13 @@ struct cipher_parm_s
size_t ciphertextlen;
};
+struct writecert_parm_s
+{
+ assuan_context_t ctx;
+ const unsigned char *certdata;
+ size_t certdatalen;
+};
+
struct writekey_parm_s
{
assuan_context_t ctx;
@@ -445,6 +452,56 @@ agent_scd_setattr (const char *name,
+/* Handle a CERTDATA inquiry. Note, we only send the data,
+ assuan_transact takes care of flushing and writing the END
+ command. */
+static int
+inq_writecert_parms (void *opaque, const char *line)
+{
+ int rc;
+ struct writecert_parm_s *parm = opaque;
+
+ if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
+ {
+ rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
+ }
+ else
+ rc = default_inq_cb (opaque, line);
+
+ return rc;
+}
+
+
+/* Send a WRITECERT command to the SCdaemon. */
+int
+agent_scd_writecert (const char *certidstr,
+ const unsigned char *certdata, size_t certdatalen)
+{
+ int rc;
+ char line[ASSUAN_LINELENGTH];
+ struct writecert_parm_s parms;
+
+ rc = start_agent ();
+ if (rc)
+ return rc;
+
+ memset (&parms, 0, sizeof parms);
+
+ snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
+ line[DIM(line)-1] = 0;
+ parms.ctx = agent_ctx;
+ parms.certdata = certdata;
+ parms.certdatalen = certdatalen;
+
+ rc = assuan_transact (agent_ctx, line, NULL, NULL,
+ inq_writecert_parms, &parms, NULL, NULL);
+
+ return rc;
+}
+
+
+
+
/* Handle a KEYDATA inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */
static int
diff --git a/g10/call-agent.h b/g10/call-agent.h
index b3e8ae2b6..63b460a90 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -76,6 +76,10 @@ int agent_scd_setattr (const char *name,
const unsigned char *value, size_t valuelen,
const char *serialno);
+/* Send a WRITECERT command to the SCdaemon. */
+int agent_scd_writecert (const char *certidstr,
+ const unsigned char *certdata, size_t certdatalen);
+
/* Send a WRITEKEY command to the SCdaemon. */
int agent_scd_writekey (int keyno, const char *serialno,
const unsigned char *keydata, size_t keydatalen);
diff --git a/g10/card-util.c b/g10/card-util.c
index 2778bb871..2d00bb3ac 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -288,6 +288,18 @@ fpr_is_zero (const char *fpr)
}
+/* Return true if the SHA1 fingerprint FPR consists only of 0xFF. */
+static int
+fpr_is_ff (const char *fpr)
+{
+ int i;
+
+ for (i=0; i < 20 && fpr[i] == '\xff'; i++)
+ ;
+ return (i == 20);
+}
+
+
/* Print all available information about the current card. */
void
card_status (FILE *fp, char *serialno, size_t serialnobuflen)
@@ -467,7 +479,10 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen)
thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
info.fpr3valid? info.fpr3 : NULL);
- if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20))
+ /* If the fingerprint is all 0xff, the key has no asssociated
+ OpenPGP certificate. */
+ if ( thefpr && !fpr_is_ff (thefpr)
+ && !get_pubkey_byfprint (pk, thefpr, 20))
{
KBNODE keyblock = NULL;
@@ -655,6 +670,58 @@ fetch_url(void)
}
+/* Read data from file FNAME up to MAXLEN characters. On error return
+ -1 and store NULl at R_BUFFER; on success return the number of
+ bytes read and store the address of a newly allocated buffer at
+ R_BUFFER. */
+static int
+get_data_from_file (const char *fname, size_t maxlen, char **r_buffer)
+{
+ FILE *fp;
+ char *data;
+ int n;
+
+ *r_buffer = NULL;
+
+ fp = fopen (fname, "rb");
+#if GNUPG_MAJOR_VERSION == 1
+ if (fp && is_secured_file (fileno (fp)))
+ {
+ fclose (fp);
+ fp = NULL;
+ errno = EPERM;
+ }
+#endif
+ if (!fp)
+ {
+ tty_printf (_("can't open `%s': %s\n"), fname, strerror (errno));
+ return -1;
+ }
+
+ data = xtrymalloc (maxlen? maxlen:1);
+ if (!data)
+ {
+ tty_printf (_("error allocating enough memory: %s\n"), strerror (errno));
+ fclose (fp);
+ return -1;
+ }
+
+ if (maxlen)
+ n = fread (data, 1, maxlen, fp);
+ else
+ n = 0;
+ fclose (fp);
+ if (n < 0)
+ {
+ tty_printf (_("error reading `%s': %s\n"), fname, strerror (errno));
+ xfree (data);
+ return -1;
+ }
+ *r_buffer = data;
+ return n;
+}
+
+
static int
change_login (const char *args)
{
@@ -664,34 +731,11 @@ change_login (const char *args)
if (args && *args == '<') /* Read it from a file */
{
- FILE *fp;
-
for (args++; spacep (args); args++)
;
- fp = fopen (args, "rb");
-#if GNUPG_MAJOR_VERSION == 1
- if (fp && is_secured_file (fileno (fp)))
- {
- fclose (fp);
- fp = NULL;
- errno = EPERM;
- }
-#endif
- if (!fp)
- {
- tty_printf (_("can't open `%s': %s\n"), args, strerror (errno));
- return -1;
- }
-
- data = xmalloc (254);
- n = fread (data, 1, 254, fp);
- fclose (fp);
+ n = get_data_from_file (args, 254, &data);
if (n < 0)
- {
- tty_printf (_("error reading `%s': %s\n"), args, strerror (errno));
- xfree (data);
- return -1;
- }
+ return -1;
}
else
{
@@ -732,35 +776,11 @@ change_private_do (const char *args, int nr)
if (args && (args = strchr (args, '<'))) /* Read it from a file */
{
- FILE *fp;
-
- /* Fixme: Factor this duplicated code out. */
for (args++; spacep (args); args++)
;
- fp = fopen (args, "rb");
-#if GNUPG_MAJOR_VERSION == 1
- if (fp && is_secured_file (fileno (fp)))
- {
- fclose (fp);
- fp = NULL;
- errno = EPERM;
- }
-#endif
- if (!fp)
- {
- tty_printf (_("can't open `%s': %s\n"), args, strerror (errno));
- return -1;
- }
-
- data = xmalloc (254);
- n = fread (data, 1, 254, fp);
- fclose (fp);
+ n = get_data_from_file (args, 254, &data);
if (n < 0)
- {
- tty_printf (_("error reading `%s': %s\n"), args, strerror (errno));
- xfree (data);
- return -1;
- }
+ return -1;
}
else
{
@@ -788,6 +808,36 @@ change_private_do (const char *args, int nr)
return rc;
}
+
+static int
+change_cert (const char *args)
+{
+ char *data;
+ int n;
+ int rc;
+
+ if (args && *args == '<') /* Read it from a file */
+ {
+ for (args++; spacep (args); args++)
+ ;
+ n = get_data_from_file (args, 16384, &data);
+ if (n < 0)
+ return -1;
+ }
+ else
+ {
+ tty_printf ("usage error: redirectrion to file required\n");
+ return -1;
+ }
+
+ rc = agent_scd_writecert ("OPENPGP.3", data, n);
+ if (rc)
+ log_error ("error writing certificate to card: %s\n", gpg_strerror (rc));
+ xfree (data);
+ return rc;
+}
+
+
static int
change_lang (void)
{
@@ -1294,7 +1344,7 @@ enum cmdids
cmdNOP = 0,
cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
- cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO,
+ cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
cmdINVCMD
};
@@ -1325,8 +1375,9 @@ static struct
{ "generate", cmdGENERATE, 1, N_("generate new keys")},
{ "passwd" , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
{ "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
- /* Note, that we do not announce this command yet. */
+ /* Note, that we do not announce these command yet. */
{ "privatedo", cmdPRIVATEDO, 0, NULL },
+ { "writecert", cmdWRITECERT, 1, NULL },
{ NULL, cmdINVCMD, 0, NULL }
};
@@ -1401,6 +1452,7 @@ card_edit (strlist_t commands)
{
int arg_number;
const char *arg_string = "";
+ const char *arg_rest = "";
char *p;
int i;
int cmd_admin_only;
@@ -1469,6 +1521,11 @@ card_edit (strlist_t commands)
trim_spaces (p);
arg_number = atoi(p);
arg_string = p;
+ arg_rest = p;
+ while (digitp (arg_rest))
+ arg_rest++;
+ while (spacep (arg_rest))
+ arg_rest++;
}
for (i=0; cmds[i].name; i++ )
@@ -1567,6 +1624,13 @@ card_edit (strlist_t commands)
change_private_do (arg_string, arg_number);
break;
+ case cmdWRITECERT:
+ if ( arg_number != 3 )
+ tty_printf ("usage: writecert 3 < FILE\n");
+ else
+ change_cert (arg_rest);
+ break;
+
case cmdFORCESIG:
toggle_forcesig ();
break;