[PATCH] agent: Send pinentry the uid of connecting process where possible.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Sun Feb 5 08:23:30 CET 2017
* agent/agent.h (server_control_s): Add field 'client_uid'.
* agent/call-pinentry.c (start_pinentry): Add uid field to assuan
option "owner" sent to pinentry.
* agent/command-ssh.c (peer_info_s): New static struct.
(get_client_pid): Rename to...
(get_client_info): Here, and extract uid in addition to pid.
(start_command_handler_ssh): Use get_client_info() instead of
get_client_pid().
* agent/command.c (start_command_handler): Use assuan_get_peercred
instead of assuan_get_pid.
--
This requires a concurrent update to pinentry to handle the new uid
field. Distributing the uid as well as the pid makes it harder for a
different user on the same machine to take advantage of any race
conditions between when a requesting process might ask for something
that needs pinentry, and when pinentry gets around to inspecting the
state of that process.
Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
---
agent/agent.h | 1 +
agent/call-pinentry.c | 5 +++--
agent/command-ssh.c | 29 +++++++++++++++++++++++------
agent/command.c | 23 +++++++++++++++++------
4 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/agent/agent.h b/agent/agent.h
index 217838472..23064a703 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -219,6 +219,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;
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index 99316653b..9d62b442f 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -553,8 +553,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);
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index 1d4453c84..40fd481ec 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -248,6 +248,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. */
@@ -3492,10 +3497,12 @@ ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
/* Return the peer's pid. Stripped down code from libassuan. */
-static unsigned long
-get_client_pid (int fd)
+static struct peer_info_s
+get_client_info (int fd)
{
+ struct peer_info_s out;
pid_t client_pid = (pid_t)(-1);
+ uid_t client_uid = (uid_t)-1;
#ifdef HAVE_SO_PEERCRED
{
@@ -3503,7 +3510,10 @@ get_client_pid (int fd)
socklen_t cl = sizeof cr;
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
- client_pid = cr.pid;
+ {
+ client_pid = cr.pid;
+ client_uid = cr.uid;
+ }
}
#elif defined (HAVE_GETPEERUCRED)
{
@@ -3511,7 +3521,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);
}
}
@@ -3522,10 +3533,13 @@ get_client_pid (int fd)
if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
client_pid = unp.unp_pid;
+ client_uid = unp.unp_euid;
}
#endif
- return client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid;
+ out.pid = (client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid);
+ out.uid = (int)client_uid;
+ return out;
}
@@ -3536,12 +3550,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));
+ peer_info = get_client_info (FD2INT(sock_client));
+ 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 c8b34e988..1aef6a154 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -3288,7 +3288,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)
@@ -3301,12 +3301,23 @@ 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));
+ ctrl->client_pid = 0;
+ ctrl->client_uid = -1;
+ }
else
- ctrl->client_pid = 0;
+ {
+ 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)
--
2.11.0
More information about the Gnupg-devel
mailing list