diff options
Diffstat (limited to '')
-rw-r--r-- | g10/ChangeLog | 12 | ||||
-rw-r--r-- | g10/card-util.c | 424 | ||||
-rw-r--r-- | g10/g10.c | 17 | ||||
-rw-r--r-- | g10/gpgv.c | 6 | ||||
-rw-r--r-- | g10/keygen.c | 210 | ||||
-rw-r--r-- | g10/main.h | 2 |
6 files changed, 420 insertions, 251 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index ae602ebdc..6f53430c3 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,15 @@ +2003-09-18 Werner Koch <[email protected]> + + * g10.c: New command --card-edit. + * card-util.c (card_status): Use tty_fprintf for all output. + (print_sha1_fpr, print_isoname): Ditto. + (get_one_name,change_name, change_url, change_login,change_lang) + (change_sex): New; taken from keygen.c. + * keygen.c (smartcard_get_one_name, smartcard_change_name) + (smartcard_change_url, smartcard_change_login_data) + (smartcard_change_lang, smartcard_change_sex): Removed. + (check_smartcard): Removed most menu items. + 2003-09-06 Werner Koch <[email protected]> * misc.c (openpgp_pk_algo_usage): Allow AUTH where SIGN is allowed. diff --git a/g10/card-util.c b/g10/card-util.c index 9f665cc74..b0754dcd2 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -34,6 +34,8 @@ #include "main.h" #include "call-agent.h" +#define CONTROL_D ('D' - 'A' + 1) + /* Change the PIN of a an OpenPGP card. This is an interactive function. */ @@ -135,32 +137,40 @@ print_sha1_fpr (FILE *fp, const unsigned char *fpr) for (i=0; i < 20 ; i+=2, fpr += 2 ) { if (i == 10 ) - putc (' ', fp); - fprintf (fp, " %02X%02X", *fpr, fpr[1]); + tty_fprintf (fp, " "); + tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]); } } else - fputs (" [none]", fp); - putc ('\n', fp); + tty_fprintf (fp, " [none]"); + tty_fprintf (fp, "\n"); } static void print_name (FILE *fp, const char *text, const char *name) { - fputs (text, fp); + tty_fprintf (fp, text); + + /* FIXME: tty_printf_utf8_string2 east everything after and + including an @ - e.g. when printing an url. */ if (name && *name) - print_utf8_string2 (fp, name, strlen (name), '\n'); + { + if (fp) + print_utf8_string2 (fp, name, strlen (name), '\n'); + else + tty_print_utf8_string2 (name, strlen (name), '\n'); + } else - fputs (_("[not set]"), fp); - putc ('\n', fp); + tty_fprintf (fp, _("[not set]")); + tty_fprintf (fp, "\n"); } static void print_isoname (FILE *fp, const char *text, const char *name) { - fputs (text, fp); + tty_fprintf (fp, text); if (name && *name) { @@ -174,16 +184,22 @@ print_isoname (FILE *fp, const char *text, const char *name) { *given = 0; given += 2; - print_utf8_string2 (fp, given, strlen (given), '\n'); + if (fp) + print_utf8_string2 (fp, given, strlen (given), '\n'); + else + tty_print_utf8_string2 (given, strlen (given), '\n'); if (*buf) - putc (' ', fp); + tty_fprintf (fp, " "); } - print_utf8_string2 (fp, buf, strlen (buf), '\n'); + if (fp) + print_utf8_string2 (fp, buf, strlen (buf), '\n'); + else + tty_print_utf8_string2 (buf, strlen (buf), '\n'); xfree (buf); } else - fputs (_("[not set]"), fp); - putc ('\n', fp); + tty_fprintf (fp, _("[not set]")); + tty_fprintf (fp, "\n"); } @@ -203,59 +219,391 @@ card_status (FILE *fp) return; } - fprintf (fp, "Application ID ...: %s\n", - info.serialno? info.serialno : "[none]"); + tty_fprintf (fp, "Application ID ...: %s\n", + info.serialno? info.serialno : "[none]"); if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) || strlen (info.serialno) != 32 ) { log_info ("not an OpenPGP card\n"); agent_release_card_info (&info); } - fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n", - info.serialno[12] == '0'?"":info.serialno+12, - info.serialno[13], - info.serialno[14] == '0'?"":info.serialno+14, - info.serialno[15]); - fprintf (fp, "Manufacturer .....: %s\n", - get_manufacturer (xtoi_2(info.serialno+16)*256 - + xtoi_2 (info.serialno+18))); - fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20); + tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n", + info.serialno[12] == '0'?"":info.serialno+12, + info.serialno[13], + info.serialno[14] == '0'?"":info.serialno+14, + info.serialno[15]); + tty_fprintf (fp, "Manufacturer .....: %s\n", + get_manufacturer (xtoi_2(info.serialno+16)*256 + + xtoi_2 (info.serialno+18))); + tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20); print_isoname (fp, "Name of cardholder: ", info.disp_name); print_name (fp, "Language prefs ...: ", info.disp_lang); - fprintf (fp, "Sex ..............: %s\n", info.disp_sex == 1? _("male"): - info.disp_sex == 2? _("female") : _("unspecified")); + tty_fprintf (fp, "Sex ..............: %s\n", + info.disp_sex == 1? _("male"): + info.disp_sex == 2? _("female") : _("unspecified")); print_name (fp, "URL of public key : ", info.pubkey_url); print_name (fp, "Login data .......: ", info.login_data); - fprintf (fp, "Signature PIN ....: %s\n", - info.chv1_cached? _("cached"): _("not cached")); - fprintf (fp, "Max. PIN lengths .: %d %d %d\n", - info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); - fprintf (fp, "PIN retry counter : %d %d %d\n", - info.chvretry[0], info.chvretry[1], info.chvretry[2]); - fputs ("Signature key ....:", fp); + tty_fprintf (fp, "Signature PIN ....: %s\n", + info.chv1_cached? _("cached"): _("not cached")); + tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", + info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); + tty_fprintf (fp, "PIN retry counter : %d %d %d\n", + info.chvretry[0], info.chvretry[1], info.chvretry[2]); + tty_fprintf (fp, "Signature key ....:"); print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL); - fputs ("Encryption key....:", fp); + tty_fprintf (fp, "Encryption key....:"); print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); - fputs ("Authentication key:", fp); + tty_fprintf (fp, "Authentication key:"); print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); - fputs ("General key info..: ", fp); + tty_fprintf (fp, "General key info..: "); if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) print_pubkey_info (fp, pk); else fputs ("[none]\n", fp); - fprintf (fp, "Signature counter : %lu\n", info.sig_counter); + tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter); free_public_key (pk); agent_release_card_info (&info); } +static char * +get_one_name (const char *prompt1, const char *prompt2) +{ + char *name; + int i; + + for (;;) + { + name = cpr_get (prompt1, prompt2); + if (!name) + return NULL; + trim_spaces (name); + cpr_kill_prompt (); + for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++) + ; + + /* The name must be in Latin-1 and not UTF-8 - lacking the code + to ensure this we restrict it to ASCII. */ + if (name[i]) + tty_printf (_("Error: Only plain ASCII is currently allowed.\n")); + else if (strchr (name, '<')) + tty_printf (_("Error: The \"<\" character may not be used.\n")); + else if (strstr (name, " ")) + tty_printf (_("Error: Double spaces are not allowed.\n")); + else + return name; + xfree (name); + } +} + + + +static int +change_name (void) +{ + char *surname = NULL, *givenname = NULL; + char *isoname, *p; + int rc; + + surname = get_one_name ("keygen.smartcard.surname", + _("Cardholder's surname: ")); + givenname = get_one_name ("keygen.smartcard.givenname", + _("Cardholder's given name: ")); + if (!surname || !givenname || (!*surname && !*givenname)) + { + xfree (surname); + xfree (givenname); + return -1; /*canceled*/ + } + + isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1); + strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname); + xfree (surname); + xfree (givenname); + for (p=isoname; *p; p++) + if (*p == ' ') + *p = '<'; + + log_debug ("setting Name to `%s'\n", isoname); + rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) ); + if (rc) + log_error ("error setting Name: %s\n", gpg_strerror (rc)); + + xfree (isoname); + return rc; +} + + +static int +change_url (void) +{ + char *url; + int rc; + + url = cpr_get ("cardedit.change_url", _("URL to retrieve public key: ")); + if (!url) + return -1; + trim_spaces (url); + cpr_kill_prompt (); + + rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) ); + if (rc) + log_error ("error setting URL: %s\n", gpg_strerror (rc)); + xfree (url); + return rc; +} + +static int +change_login (void) +{ + char *data; + int rc; + + data = cpr_get ("cardedit.change_login", + _("Login data (account name): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + rc = agent_scd_setattr ("LOGIN-DATA", data, strlen (data) ); + if (rc) + log_error ("error setting login data: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + +static int +change_lang (void) +{ + char *data, *p; + int rc; + + data = cpr_get ("cardedit.change_lang", + _("Language preferences: ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + if (strlen (data) > 8 || (strlen (data) & 1)) + { + tty_printf (_("Error: invalid length of preference string.\n")); + xfree (data); + return -1; + } + + for (p=data; *p && *p >= 'a' && *p <= 'z'; p++) + ; + if (*p) + { + tty_printf (_("Error: invalid characters in preference string.\n")); + xfree (data); + return -1; + } + + rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) ); + if (rc) + log_error ("error setting lang: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} + + +static int +change_sex (void) +{ + char *data; + const char *str; + int rc; + data = cpr_get ("cardedit.change_sex", + _("Sex ((M)ale, (F)emale or space): ")); + if (!data) + return -1; + trim_spaces (data); + cpr_kill_prompt (); + + if (!*data) + str = "9"; + else if ((*data == 'M' || *data == 'm') && !data[1]) + str = "1"; + else if ((*data == 'F' || *data == 'f') && !data[1]) + str = "2"; + else + { + tty_printf (_("Error: invalid response.\n")); + xfree (data); + return -1; + } + + rc = agent_scd_setattr ("DISP-SEX", str, 1 ); + if (rc) + log_error ("error setting sex: %s\n", gpg_strerror (rc)); + xfree (data); + return rc; +} +/* Menu to edit all user changeable values on an OpenPGP card. Only + Key creation is not handled here. */ +void +card_edit (STRLIST commands) +{ + enum cmdids { + cmdNOP = 0, + cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, + cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, + + cmdINVCMD + }; + + static struct { + const char *name; + enum cmdids id; + const char *desc; + } cmds[] = { + { N_("quit") , cmdQUIT , N_("quit this menu") }, + { N_("q") , cmdQUIT , NULL }, + { N_("help") , cmdHELP , N_("show this help") }, + { "?" , cmdHELP , NULL }, + { N_("list") , cmdLIST , N_("list all available data") }, + { N_("l") , cmdLIST , NULL }, + { N_("debug") , cmdDEBUG , NULL }, + { N_("name") , cmdNAME , N_("change card holder's name") }, + { N_("url") , cmdURL , N_("change URL to retrieve key") }, + { N_("login") , cmdLOGIN , N_("change the login name") }, + { N_("lang") , cmdLANG , N_("change the language preferences") }, + { N_("sex") , cmdSEX , N_("change card holder's sex") }, + { NULL, cmdNOP } + }; + + enum cmdids cmd = cmdNOP; + int have_commands = !!commands; + int redisplay = 1; + char *answer = NULL;; + + if (opt.command_fd != -1) + ; + else if (opt.batch && !have_commands) + { + log_error(_("can't do that in batchmode\n")); + goto leave; + } + for (;;) + { + int arg_number; + const char *arg_string = ""; + char *p; + int i; + tty_printf("\n"); + if (redisplay ) + { + card_status (NULL); + tty_printf("\n"); + redisplay = 0; + } + do + { + xfree (answer); + if (have_commands) + { + if (commands) + { + answer = xstrdup (commands->d); + commands = commands->next; + } + else if (opt.batch) + { + answer = xstrdup ("quit"); + } + else + have_commands = 0; + } + + if (!have_commands) + { + answer = cpr_get_no_help("cardedit.prompt", _("Command> ")); + cpr_kill_prompt(); + } + trim_spaces(answer); + } + while( *answer == '#' ); + + arg_number = 0; /* Yes, here is the init which egcc complains about */ + if (!*answer) + cmd = cmdLIST; /* Default to the list command */ + else if (*answer == CONTROL_D) + cmd = cmdQUIT; + else { + if ((p=strchr (answer,' '))) + { + *p++ = 0; + trim_spaces (answer); + trim_spaces (p); + arg_number = atoi(p); + arg_string = p; + } + + for (i=0; cmds[i].name; i++ ) + if (!ascii_strcasecmp (answer, cmds[i].name )) + break; + + cmd = cmds[i].id; + } + + switch (cmd) + { + case cmdHELP: + for (i=0; cmds[i].name; i++ ) + if (cmds[i].desc) + tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) ); + break; + + case cmdLIST: + redisplay = 1; + break; + + case cmdNAME: + change_name (); + break; + + case cmdURL: + change_url (); + break; + + case cmdLOGIN: + change_login (); + break; + case cmdLANG: + change_lang (); + break; + + case cmdSEX: + change_sex (); + break; + + case cmdQUIT: + goto leave; + + case cmdNOP: + break; + + case cmdINVCMD: + default: + tty_printf ("\n"); + tty_printf (_("Invalid command (try \"help\")\n")); + break; + } /* End command switch. */ + } /* End of main menu loop. */ + + leave: + xfree (answer); +} @@ -127,6 +127,7 @@ enum cmd_and_opt_values { aNull = 0, aRebuildKeydbCaches, aRefreshKeys, aCardStatus, + aCardEdit, aChangePIN, oTextmode, @@ -362,6 +363,7 @@ static ARGPARSE_OPTS opts[] = { { aImport, "import", 256 , N_("import/merge keys")}, { aFastImport, "fast-import", 256 , "@"}, { aCardStatus, "card-status", 256, N_("print the card status")}, + { aCardEdit, "card-edit", 256, N_("change data on a card")}, { aChangePIN, "change-pin", 256, N_("change a card's PIN")}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, @@ -1425,6 +1427,7 @@ main( int argc, char **argv ) case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break; case aCardStatus: set_cmd (&cmd, aCardStatus); break; + case aCardEdit: set_cmd (&cmd, aCardEdit); break; case aChangePIN: set_cmd (&cmd, aChangePIN); break; case oArmor: opt.armor = 1; opt.no_armor=0; break; @@ -2290,6 +2293,7 @@ main( int argc, char **argv ) case aEnArmor: case aFixTrustDB: case aCardStatus: + case aCardEdit: case aChangePIN: break; case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break; @@ -2789,6 +2793,19 @@ main( int argc, char **argv ) card_status (stdout); break; + case aCardEdit: + if (argc) + { + sl = NULL; + for (argc--, argv++ ; argc; argc--, argv++) + append_to_strlist (&sl, *argv); + card_edit (sl); + free_strlist (sl); + } + else + card_edit (NULL); + break; + case aChangePIN: if (!argc) change_pin (0); diff --git a/g10/gpgv.c b/g10/gpgv.c index da108d225..fb96fad5c 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -363,9 +363,9 @@ void cipher_sync( CIPHER_HANDLE c ) {} /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } void tty_printf( const char *fmt, ... ) { } -void tty_print_string( byte *p, size_t n ) { } -void tty_print_utf8_string( byte *p, size_t n ) {} -void tty_print_utf8_string2( byte *p, size_t n, size_t max_n ) {} +void tty_print_string( const byte *p, size_t n ) { } +void tty_print_utf8_string( const byte *p, size_t n ) {} +void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {} char *tty_get( const char *prompt ) { return NULL;} char *tty_get_hidden( const char *prompt ) {return NULL; } void tty_kill_prompt(void) {} diff --git a/g10/keygen.c b/g10/keygen.c index 3dbd9b402..bc98cee17 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2860,184 +2860,6 @@ show_smartcard (struct agent_card_info_s *info) free_public_key( pk ); } - -static char * -smartcard_get_one_name (const char *prompt1, const char *prompt2) -{ - char *name; - int i; - - for (;;) - { - name = cpr_get (prompt1, prompt2); - if (!name) - return NULL; - trim_spaces (name); - cpr_kill_prompt (); - for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++) - ; - - /* The name must be in Latin-1 and not UTF-8 - lacking the code - to ensure this we restrict it to ASCII. */ - if (name[i]) - tty_printf (_("Error: Only plain ASCII is currently allowed.\n")); - else if (strchr (name, '<')) - tty_printf (_("Error: The \"<\" character may not be used.\n")); - else if (strstr (name, " ")) - tty_printf (_("Error: Double spaces are not allowed.\n")); - else - return name; - xfree (name); - } -} - -static int -smartcard_change_name (const char *current_name) -{ - char *surname = NULL, *givenname = NULL; - char *isoname, *p; - int rc; - - surname = smartcard_get_one_name ("keygen.smartcard.surname", - _("Cardholder's surname: ")); - givenname = smartcard_get_one_name ("keygen.smartcard.givenname", - _("Cardholder's given name: ")); - if (!surname || !givenname || (!*surname && !*givenname)) - { - xfree (surname); - xfree (givenname); - return -1; /*canceled*/ - } - - isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1); - strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname); - xfree (surname); - xfree (givenname); - for (p=isoname; *p; p++) - if (*p == ' ') - *p = '<'; - - log_debug ("setting Name to `%s'\n", isoname); - rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) ); - if (rc) - log_error ("error setting Name: %s\n", gpg_strerror (rc)); - - xfree (isoname); - return rc; -} - - -static int -smartcard_change_url (const char *current_url) -{ - char *url; - int rc; - - url = cpr_get ("keygen.smartcard.url", _("URL to retrieve public key: ")); - if (!url) - return -1; - trim_spaces (url); - cpr_kill_prompt (); - - rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) ); - if (rc) - log_error ("error setting URL: %s\n", gpg_strerror (rc)); - xfree (url); - return rc; -} - -static int -smartcard_change_login_data (void) -{ - char *data; - int rc; - - data = cpr_get ("keygen.smartcard.login_data", - _("Login data (account name): ")); - if (!data) - return -1; - trim_spaces (data); - cpr_kill_prompt (); - - rc = agent_scd_setattr ("LOGIN-DATA", data, strlen (data) ); - if (rc) - log_error ("error setting login data: %s\n", gpg_strerror (rc)); - xfree (data); - return rc; -} - -static int -smartcard_change_lang (void) -{ - char *data, *p; - int rc; - - data = cpr_get ("keygen.smartcard.lang", - _("Language preferences: ")); - if (!data) - return -1; - trim_spaces (data); - cpr_kill_prompt (); - - if (strlen (data) > 8 || (strlen (data) & 1)) - { - tty_printf (_("Error: invalid length of preference string.\n")); - xfree (data); - return -1; - } - - for (p=data; *p && *p >= 'a' && *p <= 'z'; p++) - ; - if (*p) - { - tty_printf (_("Error: invalid characters in preference string.\n")); - xfree (data); - return -1; - } - - rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) ); - if (rc) - log_error ("error setting lang: %s\n", gpg_strerror (rc)); - xfree (data); - return rc; -} - - -static int -smartcard_change_sex (void) -{ - char *data; - const char *str; - int rc; - - data = cpr_get ("keygen.smartcard.sex", - _("Sex ((M)ale, (F)emale or space): ")); - if (!data) - return -1; - trim_spaces (data); - cpr_kill_prompt (); - - if (!*data) - str = "9"; - else if ((*data == 'M' || *data == 'm') && !data[1]) - str = "1"; - else if ((*data == 'F' || *data == 'f') && !data[1]) - str = "2"; - else - { - tty_printf (_("Error: invalid response.\n")); - xfree (data); - return -1; - } - - rc = agent_scd_setattr ("DISP-SEX", str, 1 ); - if (rc) - log_error ("error setting sex: %s\n", gpg_strerror (rc)); - xfree (data); - return rc; -} - - /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */ static int fpr_is_zero (const char *fpr) @@ -3083,11 +2905,6 @@ check_smartcard (char **r_serialno) show_smartcard (&info); tty_printf ("\n" - "N - change cardholder name\n" - "U - change public key URL\n" - "D - change login data\n" - "L - change language preferences\n" - "S - change sex\n" "K - generate all keys\n" "Q - quit\n" "\n"); @@ -3098,32 +2915,7 @@ check_smartcard (char **r_serialno) continue; rc = 0; - if ( *answer == 'N' || *answer == 'n') - { - if (!smartcard_change_name (info.disp_name)) - reread = 1; - } - else if ( *answer == 'U' || *answer == 'u') - { - if (!smartcard_change_url (info.pubkey_url)) - reread = 1; - } - else if ( *answer == 'D' || *answer == 'd') - { - if (!smartcard_change_login_data ()) - reread = 1; - } - else if ( *answer == 'L' || *answer == 'l') - { - if (!smartcard_change_lang ()) - reread = 1; - } - else if ( *answer == 'S' || *answer == 's') - { - if (!smartcard_change_sex ()) - reread = 1; - } - else if ( *answer == 'K' || *answer == 'k') + if ( *answer == 'K' || *answer == 'k') { if ( (info.fpr1valid && !fpr_is_zero (info.fpr1)) || (info.fpr2valid && !fpr_is_zero (info.fpr2)) diff --git a/g10/main.h b/g10/main.h index 2e1377ea4..320a543de 100644 --- a/g10/main.h +++ b/g10/main.h @@ -258,7 +258,7 @@ void run_in_pipemode (void); /*-- card-util.c --*/ void change_pin (int no); void card_status (FILE *fp); - +void card_edit (STRLIST commands); /*-- signal.c --*/ void init_signals(void); |