diff options
Diffstat (limited to 'scd/command.c')
-rw-r--r-- | scd/command.c | 135 |
1 files changed, 121 insertions, 14 deletions
diff --git a/scd/command.c b/scd/command.c index b4eaa8a47..e17248439 100644 --- a/scd/command.c +++ b/scd/command.c @@ -61,6 +61,8 @@ reset_notify (ASSUAN_CONTEXT ctx) { card_close (ctrl->card_ctx); ctrl->card_ctx = NULL; + xfree (ctrl->in_data.value); + ctrl->in_data.value = NULL; } } @@ -72,6 +74,63 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) } +/* If the card has not yet been opened, do it. Note that this + function returns an Assuan error, so don't map the error a second + time */ +static AssuanError +open_card (CTRL ctrl) +{ + if (!ctrl->card_ctx) + { + int rc = card_open (&ctrl->card_ctx); + if (rc) + return map_to_assuan_status (rc); + } + return 0; +} + + +/* SERIALNO + + Return the serial number of the card using a status reponse. This + functon should be used to check for the presence of a card. + + This function is special in that it can be used to reset the card. + Most other functions will return an error when a card change has + been detected and the use of this function is therefore required. + + Background: We want to keep the client clear of handling card + changes between operations; i.e. the client can assume that all + operations are doneon the same card unless he call this function. + */ +static int +cmd_serialno (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc = 0; + char *serial_and_stamp; + char *serial; + time_t stamp; + + if ((rc = open_card (ctrl))) + return rc; + + rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp); + if (rc) + return map_to_assuan_status (rc); + rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp); + xfree (serial); + if (rc < 0) + return ASSUAN_Out_Of_Core; + rc = 0; + assuan_write_status (ctx, "SERIALNO", serial_and_stamp); + free (serial_and_stamp); + return 0; +} + + + + /* LEARN [--force] Learn all useful information of the currently inserted card. When @@ -98,14 +157,8 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) int rc = 0; int idx; - /* if this is the first command issued for a new card, open the card and - and create a context */ - if (!ctrl->card_ctx) - { - rc = card_open (&ctrl->card_ctx); - if (rc) - return map_to_assuan_status (rc); - } + if ((rc = open_card (ctrl))) + return rc; /* Unless the force option is used we try a shortcut by identifying the card using a serial number and inquiring the client with @@ -221,12 +274,8 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) unsigned char *cert; size_t ncert; - if (!ctrl->card_ctx) - { - rc = card_open (&ctrl->card_ctx); - if (rc) - return map_to_assuan_status (rc); - } + if ((rc = open_card (ctrl))) + return rc; rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); if (rc) @@ -244,6 +293,61 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line) return map_to_assuan_status (rc); } + + + +/* SETDATA <hexstring> + + The client should use this command to tell us the data he want to + sign. */ +static int +cmd_setdata (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int n; + char *p; + unsigned char *buf; + + /* parse the hexstring */ + for (p=line,n=0; hexdigitp (p); p++, n++) + ; + if (*p) + return set_error (Parameter_Error, "invalid hexstring"); + if ((n&1)) + return set_error (Parameter_Error, "odd number of digits"); + n /= 2; + buf = xtrymalloc (n); + if (!buf) + return ASSUAN_Out_Of_Core; + + ctrl->in_data.value = buf; + ctrl->in_data.valuelen = n; + for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++) + buf[n] = xtoi_2 (p); + return 0; +} + + + +/* PKSIGN <hexified_id> + + */ +static int +cmd_pksign (ASSUAN_CONTEXT ctx, char *line) +{ + CTRL ctrl = assuan_get_pointer (ctx); + int rc; + + if ((rc = open_card (ctrl))) + return rc; + + + + return map_to_assuan_status (rc); +} + + + /* Tell the assuan library about our commands */ static int @@ -254,8 +358,11 @@ register_commands (ASSUAN_CONTEXT ctx) int cmd_id; int (*handler)(ASSUAN_CONTEXT, char *line); } table[] = { + { "SERIALNO", 0, cmd_serialno }, { "LEARN", 0, cmd_learn }, { "READCERT", 0, cmd_readcert }, + { "SETDATA", 0, cmd_setdata }, + { "PKSIGN", 0, cmd_pksign }, { "", ASSUAN_CMD_INPUT, NULL }, { "", ASSUAN_CMD_OUTPUT, NULL }, { NULL } |