diff --git a/agent/call-scd.c b/agent/call-scd.c new file mode 100644 index 000000000..790587352 --- /dev/null +++ b/agent/call-scd.c @@ -0,0 +1,153 @@ +/* call-scd.c - fork of the scdaemon to do SC operations + * Copyright (C) 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" +#include "../assuan/assuan.h" + +#ifdef _POSIX_OPEN_MAX +#define MAX_OPEN_FDS _POSIX_OPEN_MAX +#else +#define MAX_OPEN_FDS 20 +#endif + +static ASSUAN_CONTEXT scd_ctx = NULL; + +/* callback parameter for learn card */ +struct learn_parm_s { + int lines; + size_t size; + char *buffer; +}; + + + + +/* Fork off the SCdaemon if this has not already been done */ +static int +start_scd (void) +{ + int rc; + const char *pgmname; + ASSUAN_CONTEXT ctx; + const char *argv[3]; + + if (scd_ctx) + return 0; /* No need to serialize things because the agent is + expected to tun as a single-thread (or may be in + future using libpth) */ + + log_debug ("no running SCdaemon - starting it\n"); + + if (fflush (NULL)) + { + log_error ("error flushing pending output: %s\n", strerror (errno)); + return seterr (Write_Error); + } + + /* FIXME: change the default location of the program */ + if (!opt.scdaemon_program || !*opt.scdaemon_program) + opt.scdaemon_program = "../scd/scdaemon"; + if ( !(pgmname = strrchr (opt.scdaemon_program, '/'))) + pgmname = opt.scdaemon_program; + else + pgmname++; + + argv[0] = pgmname; + argv[1] = "--server"; + argv[2] = NULL; + + /* connect to the pinentry and perform initial handshaking */ + rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv, 0); + if (rc) + { + log_error ("can't connect to the SCdaemon: %s\n", + assuan_strerror (rc)); + return seterr (No_Scdaemon); + } + scd_ctx = ctx; + + log_debug ("connection to SCdaemon established\n"); + return 0; +} + + + +static AssuanError +learn_status_cb (void *opaque, const char *line) +{ + struct learn_parm_s *parm = opaque; + const char *keyword = line; + int keywordlen; + + for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) + ; + while (spacep (line)) + line++; + if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen)) + { + log_debug ("learn_status_cb: keypair `%s'\n", line); + } + else if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) + { + log_debug ("learn_status_cb: serialno `%s'\n", line); + } + else + log_debug ("learn_status_cb: ignoring `%.*s'\n", keywordlen, keyword); + + return 0; +} + +/* Perform the learn command and return a list of all private keys + stored on the card. */ +int +agent_learn_card (void) +{ + int rc; + struct learn_parm_s parm; + + rc = start_scd (); + if (rc) + return rc; + + rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + memset (&parm, 0, sizeof parm); + + rc = assuan_transact (scd_ctx, "LEARN --force", + NULL, NULL, NULL, NULL, + learn_status_cb, &parm); + if (rc) + return map_assuan_err (rc); + + return 0; +} + diff --git a/agent/divert-scd.c b/agent/divert-scd.c new file mode 100644 index 000000000..ca819298a --- /dev/null +++ b/agent/divert-scd.c @@ -0,0 +1,47 @@ +/* divert-scd.c - divert operations to the scdaemon + * Copyright (C) 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "agent.h" + + + +int +divert_pksign (GCRY_SEXP *s_sig, GCRY_SEXP s_hash, const char *shadow_info) +{ + return GNUPG_Not_Implemented; +} + + +int +divert_pkdecrypt (GCRY_SEXP *s_plain, GCRY_SEXP s_cipher, + const char *shadow_info) +{ + return GNUPG_Not_Implemented; +} diff --git a/assuan/ChangeLog b/assuan/ChangeLog index a46f55421..867f1250c 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,11 @@ +2002-02-27 Werner Koch + + * assuan-client.c (assuan_transact): Add 2 more arguments to + support status lines. Passing NULL yields the old behaviour. + + * assuan-handler.c (process_request): Flush data lines send + without using the data fp. + 2002-02-14 Werner Koch * assuan-inquire.c (assuan_inquire): Check for a cancel command diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index d56357dc6..41984fdac 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -57,6 +57,15 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) *okay = 2; /* data line */ *off = 2; } + else if (linelen >= 1 + && line[0] == 'S' + && (line[1] == '\0' || line[1] == ' ')) + { + *okay = 4; + *off = 1; + while (line[*off] == ' ') + ++*off; + } else if (linelen >= 2 && line[0] == 'O' && line[1] == 'K' && (line[2] == '\0' || line[2] == ' ')) @@ -101,6 +110,8 @@ _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off) * @data_cb_arg: first argument passed to @data_cb * @inquire_cb: Callback function for a inquire response * @inquire_cb_arg: first argument passed to @inquire_cb + * @status_cb: Callback function for a status response + * @status_cb_arg: first argument passed to @status_cb * * FIXME: Write documentation * @@ -114,7 +125,9 @@ assuan_transact (ASSUAN_CONTEXT ctx, AssuanError (*data_cb)(void *, const void *, size_t), void *data_cb_arg, AssuanError (*inquire_cb)(void*, const char *), - void *inquire_cb_arg) + void *inquire_cb_arg, + AssuanError (*status_cb)(void*, const char *), + void *status_cb_arg) { int rc, okay, off; unsigned char *line; @@ -181,6 +194,13 @@ assuan_transact (ASSUAN_CONTEXT ctx, goto again; } } + else if (okay == 4) + { + if (status_cb) + rc = status_cb (status_cb_arg, line); + if (!rc) + goto again; + } return rc; } diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index 1c8aded7b..69b34b4fc 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -464,6 +464,12 @@ process_request (ASSUAN_CONTEXT ctx) if (!rc && ctx->outbound.data.error) rc = ctx->outbound.data.error; } + else /* flush any data send w/o using the data fp */ + { + assuan_send_data (ctx, NULL, 0); + if (!rc && ctx->outbound.data.error) + rc = ctx->outbound.data.error; + } /* Error handling */ if (!rc) { @@ -478,7 +484,7 @@ process_request (ASSUAN_CONTEXT ctx) { char errline[256]; - if (rc < 100) + if (rc < 100) sprintf (errline, "ERR %d server fault (%.50s)", ASSUAN_Server_Fault, assuan_strerror (rc)); else diff --git a/assuan/assuan.h b/assuan/assuan.h index fed4e3468..3c679725f 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -73,6 +73,7 @@ typedef enum { ASSUAN_Inquire_Unknown = 120, ASSUAN_Inquire_Error = 121, ASSUAN_Invalid_Option = 122, + ASSUAN_Invalid_Index = 123, ASSUAN_Not_Confirmed = 128, @@ -94,7 +95,8 @@ typedef enum { ASSUAN_Card_Error = 401, ASSUAN_Invalid_Card = 402, ASSUAN_No_PKCS15_App = 403, - ASSUAN_Card_Not_Present = 404 + ASSUAN_Card_Not_Present = 404, + ASSUAN_Invalid_Id = 405 } AssuanError; @@ -185,7 +187,9 @@ assuan_transact (ASSUAN_CONTEXT ctx, AssuanError (*data_cb)(void *, const void *, size_t), void *data_cb_arg, AssuanError (*inquire_cb)(void*, const char *), - void *inquire_cb_arg); + void *inquire_cb_arg, + AssuanError (*status_cb)(void*, const char *), + void *status_cb_arg); /*-- assuan-inquire.c --*/