1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

* agent.h (server_control_s): Add connection_fd field.

* command.c (start_command_handler): Init it here.
* gpg-agent.c (agent_init_default_ctrl): and here.
* call-scd.c: Add the CTRL arg to all functions calling start_scd
and pass it to start_scd.  Changed all callers
(start_scd): Keep track of the current active connection.
(agent_reset_scd): New.
* command.c (start_command_handler): Call it here.
* learncard.c (agent_handle_learn): Add arg CTRL; changed caller.
(send_cert_back): Ditto.
This commit is contained in:
Werner Koch 2004-01-29 20:17:27 +00:00
parent e4587ba874
commit b11106ebf0
7 changed files with 138 additions and 46 deletions

View File

@ -1,3 +1,16 @@
2004-01-29 Werner Koch <wk@gnupg.org>
* agent.h (server_control_s): Add connection_fd field.
* command.c (start_command_handler): Init it here.
* gpg-agent.c (agent_init_default_ctrl): and here.
* call-scd.c: Add the CTRL arg to all functions calling start_scd
and pass it to start_scd. Changed all callers
(start_scd): Keep track of the current active connection.
(agent_reset_scd): New.
* command.c (start_command_handler): Call it here.
* learncard.c (agent_handle_learn): Add arg CTRL; changed caller.
(send_cert_back): Ditto.
2004-01-28 Werner Koch <wk@gnupg.org> 2004-01-28 Werner Koch <wk@gnupg.org>
* trustlist.c (agent_marktrusted): Check whether the trustlist is * trustlist.c (agent_marktrusted): Check whether the trustlist is
@ -18,7 +31,7 @@
* findkey.c (agent_key_from_file): Now return an error code so * findkey.c (agent_key_from_file): Now return an error code so
that we have more detailed error messages in the upper layers. that we have more detailed error messages in the upper layers.
This fixes the handling pinentry's cancel button. This fixes the handling of pinentry's cancel button.
* pksign.c (agent_pksign): Changed accordingly. * pksign.c (agent_pksign): Changed accordingly.
* pkdecrypt.c (agent_pkdecrypt): Ditto. * pkdecrypt.c (agent_pkdecrypt): Ditto.
* command.c (cmd_passwd): Ditto. * command.c (cmd_passwd): Ditto.

View File

@ -83,6 +83,7 @@ struct server_local_s;
struct server_control_s { struct server_control_s {
struct server_local_s *server_local; struct server_local_s *server_local;
int connection_fd; /* -1 or an identifier for the current connection. */
char *display; char *display;
char *ttyname; char *ttyname;
char *ttytype; char *ttytype;
@ -98,6 +99,7 @@ struct server_control_s {
}; };
typedef struct server_control_s *CTRL; typedef struct server_control_s *CTRL;
typedef struct server_control_s *ctrl_t;
struct pin_entry_info_s { struct pin_entry_info_s {
@ -194,33 +196,38 @@ int divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context);
/*-- call-scd.c --*/ /*-- call-scd.c --*/
int agent_card_learn (void (*kpinfo_cb)(void*, const char *), int agent_reset_scd (ctrl_t ctrl);
int agent_card_learn (ctrl_t ctrl,
void (*kpinfo_cb)(void*, const char *),
void *kpinfo_cb_arg, void *kpinfo_cb_arg,
void (*certinfo_cb)(void*, const char *), void (*certinfo_cb)(void*, const char *),
void *certinfo_cb_arg, void *certinfo_cb_arg,
void (*sinfo_cb)(void*, const char *, void (*sinfo_cb)(void*, const char *,
size_t, const char *), size_t, const char *),
void *sinfo_cb_arg); void *sinfo_cb_arg);
int agent_card_serialno (char **r_serialno); int agent_card_serialno (ctrl_t ctrl, char **r_serialno);
int agent_card_pksign (const char *keyid, int agent_card_pksign (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen); char **r_buf, size_t *r_buflen);
int agent_card_pkdecrypt (const char *keyid, int agent_card_pkdecrypt (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*,size_t), int (*getpin_cb)(void *, const char *, char*,size_t),
void *getpin_cb_arg, void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen); char **r_buf, size_t *r_buflen);
int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen); int agent_card_readcert (ctrl_t ctrl,
int agent_card_readkey (const char *id, unsigned char **r_buf); const char *id, char **r_buf, size_t *r_buflen);
int agent_card_scd (const char *cmdline, int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf);
int agent_card_scd (ctrl_t ctrl, const char *cmdline,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *assuan_context); void *getpin_cb_arg, void *assuan_context);
/*-- learncard.c --*/ /*-- learncard.c --*/
int agent_handle_learn (void *assuan_context); int agent_handle_learn (ctrl_t ctrl, void *assuan_context);
#endif /*AGENT_H*/ #endif /*AGENT_H*/

View File

@ -50,6 +50,17 @@ static ASSUAN_CONTEXT scd_ctx = NULL;
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
static pth_mutex_t scd_lock = PTH_MUTEX_INIT; static pth_mutex_t scd_lock = PTH_MUTEX_INIT;
#endif #endif
/* We need to keep track of the connection currently using the SCD.
For a pipe server this is all a NOP becuase the connection will
always have the conenction indicator -1. agent_reset_scd releases
the active connection; i.e. sets it back to -1, so that a new
connection can start using the SCD. If we eventually allow
multiple SCD session we will either make scdaemon multi-threaded or
fork of a new scdaemon and let it see how it can get access to a
reader.
*/
static int active_connection_fd = -1;
static int active_connection = 0;
/* callback parameter for learn card */ /* callback parameter for learn card */
struct learn_parm_s { struct learn_parm_s {
@ -162,9 +173,10 @@ atfork_cb (void *opaque, int where)
} }
/* Fork off the SCdaemon if this has not already been done */ /* Fork off the SCdaemon if this has not already been done. Note that
this fucntion alos locks the daemon. */
static int static int
start_scd (void) start_scd (ctrl_t ctrl)
{ {
int rc; int rc;
const char *pgmname; const char *pgmname;
@ -182,9 +194,20 @@ start_scd (void)
#endif #endif
if (scd_ctx) 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 /* If we are not the connection currently using the SCD, return
future using libpth) */ an error. */
if (!active_connection)
{
active_connection_fd = ctrl->connection_fd;
active_connection = 1;
}
else if (ctrl->connection_fd != active_connection_fd)
return unlock_scd (gpg_error (GPG_ERR_CONFLICT));
/* Okay, we scdaemon already started and used by us. */
return 0;
}
if (opt.verbose) if (opt.verbose)
log_info ("no running SCdaemon - starting it\n"); log_info ("no running SCdaemon - starting it\n");
@ -226,13 +249,45 @@ start_scd (void)
return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON)); return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON));
} }
scd_ctx = ctx; scd_ctx = ctx;
active_connection_fd = ctrl->connection_fd;
active_connection = 1;
if (DBG_ASSUAN) if (DBG_ASSUAN)
log_debug ("connection to SCdaemon established\n"); log_debug ("connection to SCdaemon established\n");
return 0; return 0;
} }
/* Reset the SCD if it has been used. */
int
agent_reset_scd (ctrl_t ctrl)
{
int rc = 0;
#ifdef USE_GNU_PTH
if (!pth_mutex_acquire (&scd_lock, 0, NULL))
{
log_error ("failed to acquire the SCD lock for reset\n");
return gpg_error (GPG_ERR_INTERNAL);
}
#endif
if (active_connection && active_connection_fd == ctrl->connection_fd)
{
if (scd_ctx)
rc = assuan_transact (scd_ctx, "RESET", NULL, NULL,
NULL, NULL, NULL, NULL);
active_connection_fd = -1;
active_connection = 0;
}
return unlock_scd (map_assuan_err (rc));
}
static AssuanError static AssuanError
learn_status_cb (void *opaque, const char *line) learn_status_cb (void *opaque, const char *line)
@ -264,7 +319,8 @@ learn_status_cb (void *opaque, const char *line)
/* Perform the learn command and return a list of all private keys /* Perform the learn command and return a list of all private keys
stored on the card. */ stored on the card. */
int int
agent_card_learn (void (*kpinfo_cb)(void*, const char *), agent_card_learn (ctrl_t ctrl,
void (*kpinfo_cb)(void*, const char *),
void *kpinfo_cb_arg, void *kpinfo_cb_arg,
void (*certinfo_cb)(void*, const char *), void (*certinfo_cb)(void*, const char *),
void *certinfo_cb_arg, void *certinfo_cb_arg,
@ -274,7 +330,7 @@ agent_card_learn (void (*kpinfo_cb)(void*, const char *),
int rc; int rc;
struct learn_parm_s parm; struct learn_parm_s parm;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -330,12 +386,12 @@ get_serialno_cb (void *opaque, const char *line)
/* Return the serial number of the card or an appropriate error. The /* Return the serial number of the card or an appropriate error. The
serial number is returned as a hexstring. */ serial number is returned as a hexstring. */
int int
agent_card_serialno (char **r_serialno) agent_card_serialno (ctrl_t ctrl, char **r_serialno)
{ {
int rc; int rc;
char *serialno = NULL; char *serialno = NULL;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -405,7 +461,8 @@ inq_needpin (void *opaque, const char *line)
/* Create a signature using the current card */ /* Create a signature using the current card */
int int
agent_card_pksign (const char *keyid, agent_card_pksign (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
@ -420,7 +477,7 @@ agent_card_pksign (const char *keyid,
size_t sigbuflen; size_t sigbuflen;
*r_buf = NULL; *r_buf = NULL;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -476,7 +533,8 @@ agent_card_pksign (const char *keyid,
/* Decipher INDATA using the current card. Note that the returned value is */ /* Decipher INDATA using the current card. Note that the returned value is */
int int
agent_card_pkdecrypt (const char *keyid, agent_card_pkdecrypt (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *getpin_cb_arg,
const unsigned char *indata, size_t indatalen, const unsigned char *indata, size_t indatalen,
@ -489,7 +547,7 @@ agent_card_pkdecrypt (const char *keyid,
size_t len; size_t len;
*r_buf = NULL; *r_buf = NULL;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -531,7 +589,8 @@ agent_card_pkdecrypt (const char *keyid,
/* Read a certificate with ID into R_BUF and R_BUFLEN. */ /* Read a certificate with ID into R_BUF and R_BUFLEN. */
int int
agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen) agent_card_readcert (ctrl_t ctrl,
const char *id, char **r_buf, size_t *r_buflen)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
@ -539,7 +598,7 @@ agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
size_t len; size_t len;
*r_buf = NULL; *r_buf = NULL;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -567,7 +626,7 @@ agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
/* Read a key with ID and return it in an allocate buffer pointed to /* Read a key with ID and return it in an allocate buffer pointed to
by r_BUF as a valid S-expression. */ by r_BUF as a valid S-expression. */
int int
agent_card_readkey (const char *id, unsigned char **r_buf) agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
@ -575,7 +634,7 @@ agent_card_readkey (const char *id, unsigned char **r_buf)
size_t len, buflen; size_t len, buflen;
*r_buf = NULL; *r_buf = NULL;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -642,14 +701,14 @@ pass_data_thru (void *opaque, const void *buffer, size_t length)
mechanism to pass everything verbatim to SCDAEMOPN. The PIN mechanism to pass everything verbatim to SCDAEMOPN. The PIN
inquirey is handled inside gpg-agent. */ inquirey is handled inside gpg-agent. */
int int
agent_card_scd (const char *cmdline, agent_card_scd (ctrl_t ctrl, const char *cmdline,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg, void *assuan_context) void *getpin_cb_arg, void *assuan_context)
{ {
int rc; int rc;
struct inq_needpin_s inqparm; struct inq_needpin_s inqparm;
rc = start_scd (); rc = start_scd (ctrl);
if (rc) if (rc)
return rc; return rc;

View File

@ -579,9 +579,10 @@ cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line)
static int static int
cmd_learn (ASSUAN_CONTEXT ctx, char *line) cmd_learn (ASSUAN_CONTEXT ctx, char *line)
{ {
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc; int rc;
rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL); rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
if (rc) if (rc)
log_error ("command learn failed: %s\n", gpg_strerror (rc)); log_error ("command learn failed: %s\n", gpg_strerror (rc));
return map_to_assuan_status (rc); return map_to_assuan_status (rc);
@ -771,6 +772,7 @@ start_command_handler (int listen_fd, int fd)
else else
{ {
rc = assuan_init_connected_socket_server (&ctx, fd); rc = assuan_init_connected_socket_server (&ctx, fd);
ctrl.connection_fd = fd;
} }
if (rc) if (rc)
{ {
@ -816,6 +818,8 @@ start_command_handler (int listen_fd, int fd)
} }
} }
/* Reset the SCD if needed. */
agent_reset_scd (&ctrl);
assuan_deinit_server (ctx); assuan_deinit_server (ctx);
if (ctrl.display) if (ctrl.display)

View File

@ -81,7 +81,7 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
for (;;) for (;;)
{ {
rc = agent_card_serialno (&serialno); rc = agent_card_serialno (ctrl, &serialno);
if (!rc) if (!rc)
{ {
log_debug ("detected card with S/N %s\n", serialno); log_debug ("detected card with S/N %s\n", serialno);
@ -108,6 +108,13 @@ ask_for_card (CTRL ctrl, const unsigned char *shadow_info, char **r_kid)
if (!rc) if (!rc)
{ {
/* We better reset the SCD now. This is kludge requred
because the scdaemon is currently not always able to
detect the presence of a card. With a fully working
scdaemon this would not be required; i.e. the pkcs#15
support does not require it becuase OpenSC correclty
detects a present card. */
agent_reset_scd (ctrl);
if (asprintf (&desc, if (asprintf (&desc,
"%s:%%0A%%0A" "%s:%%0A%%0A"
" \"%.*s\"", " \"%.*s\"",
@ -230,7 +237,7 @@ divert_pksign (CTRL ctrl,
if (rc) if (rc)
return rc; return rc;
rc = agent_card_pksign (kid, getpin_cb, ctrl, rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl,
data, ndata, &sigval, &siglen); data, ndata, &sigval, &siglen);
if (!rc) if (!rc)
*r_sig = sigval; *r_sig = sigval;
@ -294,7 +301,7 @@ divert_pkdecrypt (CTRL ctrl,
if (rc) if (rc)
return rc; return rc;
rc = agent_card_pkdecrypt (kid, getpin_cb, ctrl, rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl,
ciphertext, ciphertextlen, ciphertext, ciphertextlen,
&plaintext, &plaintextlen); &plaintext, &plaintextlen);
if (!rc) if (!rc)
@ -310,7 +317,7 @@ divert_pkdecrypt (CTRL ctrl,
int int
divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context) divert_generic_cmd (CTRL ctrl, const char *cmdline, void *assuan_context)
{ {
return agent_card_scd (cmdline, getpin_cb, ctrl, assuan_context); return agent_card_scd (ctrl, cmdline, getpin_cb, ctrl, assuan_context);
} }

View File

@ -784,6 +784,8 @@ agent_exit (int rc)
void void
agent_init_default_ctrl (struct server_control_s *ctrl) agent_init_default_ctrl (struct server_control_s *ctrl)
{ {
ctrl->connection_fd = -1;
/* Note we ignore malloc errors because we can't do much about it /* Note we ignore malloc errors because we can't do much about it
and the request will fail anyway shortly after this and the request will fail anyway shortly after this
initialization. */ initialization. */

View File

@ -255,13 +255,13 @@ make_shadow_info (const char *serialno, const char *idstring)
} }
static int static int
send_cert_back (const char *id, void *assuan_context) send_cert_back (ctrl_t ctrl, const char *id, void *assuan_context)
{ {
int rc; int rc;
char *derbuf; char *derbuf;
size_t derbuflen; size_t derbuflen;
rc = agent_card_readcert (id, &derbuf, &derbuflen); rc = agent_card_readcert (ctrl, id, &derbuf, &derbuflen);
if (rc) if (rc)
{ {
log_error ("error reading certificate: %s\n", log_error ("error reading certificate: %s\n",
@ -287,7 +287,7 @@ send_cert_back (const char *id, void *assuan_context)
/* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new /* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new
certificates are send via Assuan */ certificates are send via Assuan */
int int
agent_handle_learn (void *assuan_context) agent_handle_learn (ctrl_t ctrl, void *assuan_context)
{ {
int rc; int rc;
struct kpinfo_cb_parm_s parm; struct kpinfo_cb_parm_s parm;
@ -313,12 +313,12 @@ agent_handle_learn (void *assuan_context)
memset (&sparm, 0, sizeof sparm); memset (&sparm, 0, sizeof sparm);
/* Check whether a card is present and get the serial number */ /* Check whether a card is present and get the serial number */
rc = agent_card_serialno (&serialno); rc = agent_card_serialno (ctrl, &serialno);
if (rc) if (rc)
goto leave; goto leave;
/* now gather all the available info */ /* now gather all the available info */
rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm, rc = agent_card_learn (ctrl, kpinfo_cb, &parm, certinfo_cb, &cparm,
sinfo_cb, &sparm); sinfo_cb, &sparm);
if (!rc && (parm.error || cparm.error || sparm.error)) if (!rc && (parm.error || cparm.error || sparm.error))
rc = parm.error? parm.error : cparm.error? cparm.error : sparm.error; rc = parm.error? parm.error : cparm.error? cparm.error : sparm.error;
@ -354,7 +354,7 @@ agent_handle_learn (void *assuan_context)
if (assuan_context) if (assuan_context)
{ {
rc = send_cert_back (citem->id, assuan_context); rc = send_cert_back (ctrl, citem->id, assuan_context);
if (rc) if (rc)
goto leave; goto leave;
citem->done = 1; citem->done = 1;
@ -380,7 +380,7 @@ agent_handle_learn (void *assuan_context)
continue; continue;
/* unknown - store it */ /* unknown - store it */
rc = agent_card_readkey (item->id, &pubkey); rc = agent_card_readkey (ctrl, item->id, &pubkey);
if (rc) if (rc)
{ {
log_debug ("agent_card_readkey failed: %s\n", gpg_strerror (rc)); log_debug ("agent_card_readkey failed: %s\n", gpg_strerror (rc));
@ -430,7 +430,7 @@ agent_handle_learn (void *assuan_context)
} }
if (!citem) if (!citem)
{ {
rc = send_cert_back (item->id, assuan_context); rc = send_cert_back (ctrl, item->id, assuan_context);
if (rc) if (rc)
goto leave; goto leave;
} }