diff options
author | Werner Koch <wk@gnupg.org> | 2008-09-23 11:57:45 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-09-23 11:57:45 +0200 |
commit | f899b9683b7123b7bacd5de91fb49fd2412b9116 (patch) | |
tree | b6b89477ec7016c1d9902442db6a98e980d49a5f /g10 | |
parent | * keyserver.c (keyserver_import_cert): Allow keyserver URLs in (diff) | |
download | gnupg2-f899b9683b7123b7bacd5de91fb49fd2412b9116.tar.xz gnupg2-f899b9683b7123b7bacd5de91fb49fd2412b9116.zip |
Support the Certifciate DO of the v2 OpenPGP cards.
Diffstat (limited to 'g10')
-rw-r--r-- | g10/ChangeLog | 11 | ||||
-rw-r--r-- | g10/call-agent.c | 57 | ||||
-rw-r--r-- | g10/call-agent.h | 4 | ||||
-rw-r--r-- | g10/card-util.c | 172 |
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; |