diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/agent.h | 5 | ||||
-rw-r--r-- | agent/call-pinentry.c | 149 | ||||
-rw-r--r-- | agent/call-scd.c | 41 | ||||
-rw-r--r-- | agent/command-ssh.c | 27 | ||||
-rw-r--r-- | agent/command.c | 20 | ||||
-rw-r--r-- | agent/protect.c | 6 |
6 files changed, 120 insertions, 128 deletions
diff --git a/agent/agent.h b/agent/agent.h index f5df75e6e..bf8d244a0 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -226,6 +226,7 @@ struct server_control_s char *lc_ctype; char *lc_messages; unsigned long client_pid; + int client_uid; /* The current pinentry mode. */ pinentry_mode_t pinentry_mode; @@ -254,6 +255,10 @@ struct server_control_s /* The current S2K which might be different from the calibrated count. */ unsigned long s2k_count; + + /* If pinentry is active for this thread. It can be more than 1, + when pinentry is called recursively. */ + int pinentry_active; }; diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 6a5c1fe1e..af4eb06f2 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -67,12 +67,6 @@ static struct } entry_features; -/* The control variable of the connection owning the current pinentry. - This is only valid if ENTRY_CTX is not NULL. Note, that we care - only about the value of the pointer and that it should never be - dereferenced. */ -static ctrl_t entry_owner; - /* A mutex used to serialize access to the pinentry. */ static npth_mutex_t entry_lock; @@ -128,7 +122,7 @@ agent_query_dump_state (void) void agent_reset_query (ctrl_t ctrl) { - if (entry_ctx && popup_tid && entry_owner == ctrl) + if (entry_ctx && popup_tid && ctrl->pinentry_active) { agent_popup_message_stop (ctrl); } @@ -140,7 +134,7 @@ agent_reset_query (ctrl_t ctrl) stalled pinentry does not block other threads. Fixme: We should have a timeout in Assuan for the disconnect operation. */ static gpg_error_t -unlock_pinentry (gpg_error_t rc) +unlock_pinentry (ctrl_t ctrl, gpg_error_t rc) { assuan_context_t ctx = entry_ctx; int err; @@ -177,15 +171,18 @@ unlock_pinentry (gpg_error_t rc) } } - entry_ctx = NULL; - err = npth_mutex_unlock (&entry_lock); - if (err) + if (--ctrl->pinentry_active == 0) { - log_error ("failed to release the entry lock: %s\n", strerror (err)); - if (!rc) - rc = gpg_error_from_errno (err); + entry_ctx = NULL; + err = npth_mutex_unlock (&entry_lock); + if (err) + { + log_error ("failed to release the entry lock: %s\n", strerror (err)); + if (!rc) + rc = gpg_error_from_errno (err); + } + assuan_release (ctx); } - assuan_release (ctx); return rc; } @@ -288,6 +285,14 @@ start_pinentry (ctrl_t ctrl) char *flavor_version; int err; + if (ctrl->pinentry_active) + { + /* It's trying to use pinentry recursively. In this situation, + the thread holds ENTRY_LOCK already. */ + ctrl->pinentry_active++; + return 0; + } + npth_clock_gettime (&abstime); abstime.tv_sec += LOCK_TIMEOUT; err = npth_mutex_timedlock (&entry_lock, &abstime); @@ -302,8 +307,6 @@ start_pinentry (ctrl_t ctrl) return rc; } - entry_owner = ctrl; - if (entry_ctx) return 0; @@ -325,7 +328,7 @@ start_pinentry (ctrl_t ctrl) the Wine implementation does not flush stdin,stdout and stderr - see above. Let's try to ignore the error. */ #ifndef HAVE_W32_SYSTEM - return unlock_pinentry (tmperr); + return unlock_pinentry (ctrl, tmperr); #endif } @@ -371,6 +374,10 @@ start_pinentry (ctrl_t ctrl) log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc)); return rc; } + + ctrl->pinentry_active = 1; + entry_ctx = ctx; + /* We don't want to log the pinentry communication to make the logs easier to read. We might want to add a new debug option to enable pinentry logging. */ @@ -382,17 +389,15 @@ start_pinentry (ctrl_t ctrl) that atfork is used to change the environment for pinentry. We start the server in detached mode to suppress the console window under Windows. */ - rc = assuan_pipe_connect (ctx, full_pgmname, argv, + rc = assuan_pipe_connect (entry_ctx, full_pgmname, argv, no_close_list, atfork_cb, ctrl, ASSUAN_PIPE_CONNECT_DETACHED); if (rc) { log_error ("can't connect to the PIN entry module '%s': %s\n", full_pgmname, gpg_strerror (rc)); - assuan_release (ctx); - return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY)); + return unlock_pinentry (ctrl, gpg_error (GPG_ERR_NO_PIN_ENTRY)); } - entry_ctx = ctx; if (DBG_IPC) log_debug ("connection to PIN entry established\n"); @@ -402,65 +407,65 @@ start_pinentry (ctrl_t ctrl) { char *optstr; if (asprintf (&optstr, "OPTION pinentry-user-data=%s", value) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } rc = assuan_transact (entry_ctx, opt.no_grab? "OPTION no-grab":"OPTION grab", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); value = session_env_getenv (ctrl->session_env, "GPG_TTY"); if (value) { char *optstr; if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } value = session_env_getenv (ctrl->session_env, "TERM"); if (value) { char *optstr; if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (ctrl->lc_ctype) { char *optstr; if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (ctrl->lc_messages) { char *optstr; if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } @@ -476,7 +481,7 @@ start_pinentry (ctrl_t ctrl) rc = assuan_transact (entry_ctx, "OPTION allow-external-password-cache", NULL, NULL, NULL, NULL, NULL, NULL); if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (opt.allow_emacs_pinentry) @@ -486,7 +491,7 @@ start_pinentry (ctrl_t ctrl) rc = assuan_transact (entry_ctx, "OPTION allow-emacs-prompt", NULL, NULL, NULL, NULL, NULL, NULL); if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } @@ -524,7 +529,7 @@ start_pinentry (ctrl_t ctrl) if (*s == '|' && (s2=strchr (s+1,'|'))) s = s2+1; if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 ) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); xfree (optstr); @@ -593,8 +598,9 @@ start_pinentry (ctrl_t ctrl) nodename = utsbuf.nodename; #endif /*!HAVE_W32_SYSTEM*/ - if ((optstr = xtryasprintf ("OPTION owner=%lu %s", - ctrl->client_pid, nodename))) + if ((optstr = xtryasprintf ("OPTION owner=%lu/%d %s", + ctrl->client_pid, ctrl->client_uid, + nodename))) { assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL); @@ -651,8 +657,8 @@ start_pinentry (ctrl_t ctrl) rc = agent_inq_pinentry_launched (ctrl, pinentry_pid, flavor_version); if (gpg_err_code (rc) == GPG_ERR_CANCELED || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED) - return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT, - gpg_err_code (rc))); + return unlock_pinentry (ctrl, gpg_err_make (GPG_ERR_SOURCE_DEFAULT, + gpg_err_code (rc))); rc = 0; } @@ -1022,18 +1028,18 @@ agent_askpin (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); build_cmd_setdesc (line, DIM(line), desc_text); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); snprintf (line, DIM(line), "SETPROMPT %s", prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:")); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); /* If a passphrase quality indicator has been requested and a minimum passphrase length has not been disabled, send the command @@ -1042,7 +1048,7 @@ agent_askpin (ctrl_t ctrl, { rc = setup_qualitybar (ctrl); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (initial_errtext) @@ -1051,7 +1057,7 @@ agent_askpin (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (pininfo->with_repeat) @@ -1082,7 +1088,7 @@ agent_askpin (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); errtext = NULL; } @@ -1092,7 +1098,7 @@ agent_askpin (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL); @@ -1120,7 +1126,7 @@ agent_askpin (ctrl_t ctrl, errtext = is_pin? L_("PIN too long") : L_("Passphrase too long"); else if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (!errtext && pininfo->min_digits) { @@ -1146,7 +1152,7 @@ agent_askpin (ctrl_t ctrl, || gpg_err_code (rc) == GPG_ERR_BAD_PIN) errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase")); else if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (!errtext) @@ -1154,7 +1160,7 @@ agent_askpin (ctrl_t ctrl, if (pininfo->with_repeat && (pinentry_status & PINENTRY_STATUS_PIN_REPEATED)) pininfo->repeat_okay = 1; - return unlock_pinentry (0); /* okay, got a PIN or passphrase */ + return unlock_pinentry (ctrl, 0); /* okay, got a PIN or passphrase */ } if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE)) @@ -1163,7 +1169,7 @@ agent_askpin (ctrl_t ctrl, pininfo->failed_tries --; } - return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN + return unlock_pinentry (ctrl, gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN : GPG_ERR_BAD_PASSPHRASE)); } @@ -1229,7 +1235,7 @@ agent_get_passphrase (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (desc) @@ -1238,18 +1244,18 @@ agent_get_passphrase (ctrl_t ctrl, snprintf (line, DIM(line), "RESET"); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); snprintf (line, DIM(line), "SETPROMPT %s", prompt); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (with_qualitybar && opt.min_passphrase_len) { rc = setup_qualitybar (ctrl); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (errtext) @@ -1257,14 +1263,14 @@ agent_get_passphrase (ctrl_t ctrl, snprintf (line, DIM(line), "SETERROR %s", errtext); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } memset (&parm, 0, sizeof parm); parm.size = ASSUAN_LINELENGTH/2 - 5; parm.buffer = gcry_malloc_secure (parm.size+10); if (!parm.buffer) - return unlock_pinentry (out_of_core ()); + return unlock_pinentry (ctrl, out_of_core ()); saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL); assuan_begin_confidential (entry_ctx); @@ -1288,7 +1294,7 @@ agent_get_passphrase (ctrl_t ctrl, xfree (parm.buffer); else *retpass = parm.buffer; - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } @@ -1332,7 +1338,7 @@ agent_get_confirmation (ctrl_t ctrl, rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (ok) { @@ -1340,7 +1346,7 @@ agent_get_confirmation (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } if (notok) { @@ -1363,7 +1369,7 @@ agent_get_confirmation (ctrl_t ctrl, NULL, NULL, NULL, NULL, NULL, NULL); } if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } rc = assuan_transact (entry_ctx, "CONFIRM", @@ -1371,7 +1377,7 @@ agent_get_confirmation (ctrl_t ctrl, if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } @@ -1405,7 +1411,7 @@ agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn) rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (ok_btn) { @@ -1413,7 +1419,7 @@ agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn) rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL, @@ -1421,7 +1427,7 @@ agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn) if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED) rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED); - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } @@ -1469,19 +1475,19 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn) snprintf (line, DIM(line), "RESET"); rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); if (ok_btn) { snprintf (line, DIM(line), "SETOK %s", ok_btn); rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL); if (rc) - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } err = npth_attr_init (&tattr); if (err) - return unlock_pinentry (gpg_error_from_errno (err)); + return unlock_pinentry (ctrl, gpg_error_from_errno (err)); npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE); popup_finished = 0; @@ -1492,7 +1498,7 @@ agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn) rc = gpg_error_from_errno (err); log_error ("error spawning popup message handler: %s\n", strerror (err) ); - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } npth_setname_np (popup_tid, "popup-message"); @@ -1551,10 +1557,9 @@ agent_popup_message_stop (ctrl_t ctrl) /* Thread IDs are opaque, but we try our best here by resetting it to the same content that a static global variable has. */ memset (&popup_tid, '\0', sizeof (popup_tid)); - entry_owner = NULL; /* Now we can close the connection. */ - unlock_pinentry (0); + unlock_pinentry (ctrl, 0); } int @@ -1580,5 +1585,5 @@ agent_clear_passphrase (ctrl_t ctrl, rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); - return unlock_pinentry (rc); + return unlock_pinentry (ctrl, rc); } diff --git a/agent/call-scd.c b/agent/call-scd.c index cf61a3546..6ce0cddfb 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -89,7 +89,6 @@ struct inq_needpin_parm_s const char *getpin_cb_desc; assuan_context_t passthru; /* If not NULL, pass unknown inquiries up to the caller. */ - int any_inq_seen; /* The next fields are used by inq_writekey_parm. */ const unsigned char *keydata; @@ -727,7 +726,6 @@ inq_needpin (void *opaque, const char *line) size_t pinlen; int rc; - parm->any_inq_seen = 1; if ((s = has_leading_keyword (line, "NEEDPIN"))) { line = s; @@ -811,30 +809,6 @@ hash_algo_option (int algo) } -static gpg_error_t -cancel_inquire (ctrl_t ctrl, gpg_error_t rc) -{ - gpg_error_t oldrc = rc; - - /* The inquire callback was called and transact returned a - cancel error. We assume that the inquired process sent a - CANCEL. The passthrough code is not able to pass on the - CANCEL and thus scdaemon would stuck on this. As a - workaround we send a CANCEL now. */ - rc = assuan_write_line (ctrl->scd_local->ctx, "CAN"); - if (!rc) { - char *line; - size_t len; - - rc = assuan_read_line (ctrl->scd_local->ctx, &line, &len); - if (!rc) - rc = oldrc; - } - - return rc; -} - - /* Create a signature using the current card. MDALGO is either 0 or * gives the digest algorithm. DESC_TEXT is an additional parameter * passed to GETPIN_CB. */ @@ -875,7 +849,6 @@ agent_card_pksign (ctrl_t ctrl, inqparm.getpin_cb_arg = getpin_cb_arg; inqparm.getpin_cb_desc = desc_text; inqparm.passthru = 0; - inqparm.any_inq_seen = 0; inqparm.keydata = NULL; inqparm.keydatalen = 0; @@ -888,9 +861,6 @@ agent_card_pksign (ctrl_t ctrl, put_membuf_cb, &data, inq_needpin, &inqparm, NULL, NULL); - if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED || - gpg_err_code(rc) == GPG_ERR_ASS_CANCELED)) - rc = cancel_inquire (ctrl, rc); if (rc) { @@ -974,7 +944,6 @@ agent_card_pkdecrypt (ctrl_t ctrl, inqparm.getpin_cb_arg = getpin_cb_arg; inqparm.getpin_cb_desc = desc_text; inqparm.passthru = 0; - inqparm.any_inq_seen = 0; inqparm.keydata = NULL; inqparm.keydatalen = 0; snprintf (line, DIM(line), "PKDECRYPT %s", keyid); @@ -982,9 +951,6 @@ agent_card_pkdecrypt (ctrl_t ctrl, put_membuf_cb, &data, inq_needpin, &inqparm, padding_info_cb, r_padding); - if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED || - gpg_err_code(rc) == GPG_ERR_ASS_CANCELED)) - rc = cancel_inquire (ctrl, rc); if (rc) { @@ -1111,15 +1077,11 @@ agent_card_writekey (ctrl_t ctrl, int force, const char *serialno, parms.getpin_cb_arg = getpin_cb_arg; parms.getpin_cb_desc= NULL; parms.passthru = 0; - parms.any_inq_seen = 0; parms.keydata = keydata; parms.keydatalen = keydatalen; rc = assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL, inq_writekey_parms, &parms, NULL, NULL); - if (parms.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED || - gpg_err_code(rc) == GPG_ERR_ASS_CANCELED)) - rc = cancel_inquire (ctrl, rc); return unlock_scd (ctrl, rc); } @@ -1344,7 +1306,6 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline, inqparm.getpin_cb_arg = getpin_cb_arg; inqparm.getpin_cb_desc = NULL; inqparm.passthru = assuan_context; - inqparm.any_inq_seen = 0; inqparm.keydata = NULL; inqparm.keydatalen = 0; @@ -1354,8 +1315,6 @@ agent_card_scd (ctrl_t ctrl, const char *cmdline, pass_data_thru, assuan_context, inq_needpin, &inqparm, pass_status_thru, assuan_context); - if (inqparm.any_inq_seen && gpg_err_code(rc) == GPG_ERR_ASS_CANCELED) - rc = cancel_inquire (ctrl, rc); assuan_set_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS, saveflag); if (rc) diff --git a/agent/command-ssh.c b/agent/command-ssh.c index 9d45a1864..866f43959 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -255,6 +255,11 @@ static gpg_error_t ssh_signature_encoder_eddsa (ssh_key_type_spec_t *spec, static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment); +struct peer_info_s +{ + unsigned long pid; + int uid; +}; /* Global variables. */ @@ -3581,10 +3586,11 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock) /* Return the peer's pid. */ -static unsigned long -get_client_pid (int fd) +static void +get_client_info (int fd, struct peer_info_s *out) { - pid_t client_pid = (pid_t)0; + pid_t client_pid = (pid_t)(-1); + uid_t client_uid = (uid_t)-1; #ifdef SO_PEERCRED { @@ -3599,8 +3605,10 @@ get_client_pid (int fd) { #if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID) client_pid = cr.pid; + client_uid = cr.uid; #elif defined (HAVE_STRUCT_UCRED_CR_PID) client_pid = cr.cr_pid; + client_pid = cr.cr_uid; #else #error "Unknown SO_PEERCRED struct" #endif @@ -3611,6 +3619,7 @@ get_client_pid (int fd) socklen_t len = sizeof (pid_t); getsockopt (fd, SOL_LOCAL, LOCAL_PEERPID, &client_pid, &len); + getsockopt (fd, SOL_LOCAL, LOCAL_PEERUID, &client_uid, &len); } #elif defined (LOCAL_PEEREID) { @@ -3619,6 +3628,7 @@ get_client_pid (int fd) if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1) client_pid = unp.unp_pid; + client_uid = unp.unp_euid; } #elif defined (HAVE_GETPEERUCRED) { @@ -3626,7 +3636,8 @@ get_client_pid (int fd) if (getpeerucred (fd, &ucred) != -1) { - client_pid= ucred_getpid (ucred); + client_pid = ucred_getpid (ucred); + client_uid = ucred_geteuid (ucred); ucred_free (ucred); } } @@ -3634,7 +3645,8 @@ get_client_pid (int fd) (void)fd; #endif - return (unsigned long)client_pid; + out->pid = (client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid); + out->uid = (int)client_uid; } @@ -3645,12 +3657,15 @@ start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client) estream_t stream_sock = NULL; gpg_error_t err; int ret; + struct peer_info_s peer_info; err = agent_copy_startup_env (ctrl); if (err) goto out; - ctrl->client_pid = get_client_pid (FD2INT(sock_client)); + get_client_info (FD2INT(sock_client), &peer_info); + ctrl->client_pid = peer_info.pid; + ctrl->client_uid = peer_info.uid; /* Create stream from socket. */ stream_sock = es_fdopen (FD2INT(sock_client), "r+"); diff --git a/agent/command.c b/agent/command.c index e20361a11..3b249b1bd 100644 --- a/agent/command.c +++ b/agent/command.c @@ -874,7 +874,7 @@ static const char hlp_genkey[] = "\n" " C: GENKEY\n" " S: INQUIRE KEYPARAM\n" - " C: D (genkey (rsa (nbits 2048)))\n" + " C: D (genkey (rsa (nbits 3072)))\n" " C: END\n" " S: D (public-key\n" " S: D (rsa (n 326487324683264) (e 10001)))\n" @@ -3331,7 +3331,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd) for (;;) { - pid_t client_pid; + assuan_peercred_t client_creds; rc = assuan_accept (ctx); if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1) @@ -3344,12 +3344,20 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd) break; } - client_pid = assuan_get_pid (ctx); - ctrl->server_local->connect_from_self = (client_pid == getpid ()); - if (client_pid != ASSUAN_INVALID_PID) - ctrl->client_pid = (unsigned long)client_pid; + rc = assuan_get_peercred (ctx, &client_creds); + if (rc) + { + log_info ("Assuan get_peercred failed: %s\n", gpg_strerror (rc)); + client_creds->pid = assuan_get_pid (ctx); + ctrl->client_uid = -1; + } + ctrl->server_local->connect_from_self = + (client_creds->pid == getpid ()); + if (client_creds->pid != ASSUAN_INVALID_PID) + ctrl->client_pid = (unsigned long)client_creds->pid; else ctrl->client_pid = 0; + ctrl->client_uid = client_creds->uid; rc = assuan_process (ctx); if (rc) diff --git a/agent/protect.c b/agent/protect.c index c257861e2..9b262a978 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -159,7 +159,7 @@ calibrate_s2k_count_one (unsigned long count) /* Measure the time we need to do the hash operations and deduce an - S2K count which requires about 100ms of time. */ + S2K count which requires roughly some targeted amount of time. */ static unsigned long calibrate_s2k_count (void) { @@ -171,11 +171,11 @@ calibrate_s2k_count (void) ms = calibrate_s2k_count_one (count); if (opt.verbose > 1) log_info ("S2K calibration: %lu -> %lums\n", count, ms); - if (ms > 100) + if (ms > AGENT_S2K_CALIBRATION) break; } - count = (unsigned long)(((double)count / ms) * 100); + count = (unsigned long)(((double)count / ms) * AGENT_S2K_CALIBRATION); count /= 1024; count *= 1024; if (count < 65536) |