Skip to content

Commit 80162f9

Browse files
committed
upstream: Move agent listener sockets from /tmp to under
~/.ssh/agent for both ssh-agent(1) and forwarded sockets in sshd(8). This ensures processes (such as Firefox) that have restricted filesystem access that includes /tmp (via unveil(3)) do not have the ability to use keys in an agent. Moving the default directory has the consequence that the OS will no longer clean up stale agent sockets, so ssh-agent now gains this ability. To support $HOME on NFS, the socket path includes a truncated hash of the hostname. ssh-agent will by default only clean up sockets from the same hostname. ssh-agent gains some new flags: -U suppresses the automatic cleanup of stale sockets when it starts. -u forces a cleanup without keeping a running agent, -uu forces a cleanup that ignores the hostname. -T makes ssh-agent put the socket back in /tmp. feedback deraadt@ naddy@, doitdoitdoit deraadt@ OpenBSD-Commit-ID: 8383dabd98092fe5498d5f7f15c7d314b03a93e1
1 parent 566443b commit 80162f9

File tree

8 files changed

+136
-57
lines changed

8 files changed

+136
-57
lines changed

Makefile.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \
140140
auth2-gss.o gss-serv.o gss-serv-krb5.o \
141141
loginrec.o auth-pam.o auth-shadow.o auth-sia.o \
142142
sftp-server.o sftp-common.o \
143-
uidswap.o platform-listen.o $(SKOBJS)
143+
uidswap.o platform-listen.o misc-agent.o $(SKOBJS)
144144

145145
SSHD_AUTH_OBJS=sshd-auth.o \
146146
auth2-methods.o \
@@ -155,15 +155,15 @@ SSHD_AUTH_OBJS=sshd-auth.o \
155155
sandbox-null.o sandbox-rlimit.o sandbox-darwin.o \
156156
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-solaris.o \
157157
sftp-server.o sftp-common.o \
158-
uidswap.o $(SKOBJS)
158+
uidswap.o misc-agent.o $(SKOBJS)
159159

160160
SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o
161161

162162
SCP_OBJS= scp.o progressmeter.o $(SFTP_CLIENT_OBJS)
163163

164164
SSHADD_OBJS= ssh-add.o $(SKOBJS)
165165

166-
SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS)
166+
SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o misc-agent.o $(SKOBJS)
167167

168168
SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS)
169169

hostfile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: hostfile.c,v 1.97 2025/04/30 05:26:15 djm Exp $ */
1+
/* $OpenBSD: hostfile.c,v 1.98 2025/05/05 02:48:07 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <ylo@cs.hut.fi>
44
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland

misc.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: misc.c,v 1.198 2024/10/24 03:14:37 djm Exp $ */
1+
/* $OpenBSD: misc.c,v 1.199 2025/05/05 02:48:06 djm Exp $ */
22
/*
33
* Copyright (c) 2000 Markus Friedl. All rights reserved.
44
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
@@ -3138,3 +3138,18 @@ signal_is_crash(int sig)
31383138
}
31393139
return 0;
31403140
}
3141+
3142+
char *
3143+
get_homedir(void)
3144+
{
3145+
char *cp;
3146+
struct passwd *pw;
3147+
3148+
if ((cp = getenv("HOME")) != NULL && *cp != '\0')
3149+
return xstrdup(cp);
3150+
3151+
if ((pw = getpwuid(getuid())) != NULL && *pw->pw_dir != '\0')
3152+
return xstrdup(pw->pw_dir);
3153+
3154+
return NULL;
3155+
}

misc.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: misc.h,v 1.110 2024/09/25 01:24:04 djm Exp $ */
1+
/* $OpenBSD: misc.h,v 1.111 2025/05/05 02:48:06 djm Exp $ */
22

33
/*
44
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -108,6 +108,7 @@ int parse_pattern_interval(const char *, char **, int *);
108108
int path_absolute(const char *);
109109
int stdfd_devnull(int, int, int);
110110
int lib_contains_symbol(const char *, const char *);
111+
char *get_homedir(void);
111112

112113
void sock_set_v6only(int);
113114

@@ -231,6 +232,11 @@ int ptimeout_get_ms(struct timespec *pt);
231232
struct timespec *ptimeout_get_tsp(struct timespec *pt);
232233
int ptimeout_isset(struct timespec *pt);
233234

235+
/* misc-agent.c */
236+
char *agent_hostname_hash(void);
237+
int agent_listener(const char *, const char *, int *, char **);
238+
void agent_cleanup_stale(const char *, int);
239+
234240
/* readpass.c */
235241

236242
#define RP_ECHO 0x0001

pathnames.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: pathnames.h,v 1.32 2024/05/17 00:30:24 djm Exp $ */
1+
/* $OpenBSD: pathnames.h,v 1.34 2025/05/05 02:48:06 djm Exp $ */
22

33
/*
44
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -67,6 +67,13 @@
6767
*/
6868
#define _PATH_SSH_USER_DIR ".ssh"
6969

70+
71+
/*
72+
* The directory in which ssh-agent sockets and agent sockets forwarded by
73+
* sshd reside. This directory should not be world-readable.
74+
*/
75+
#define _PATH_SSH_AGENT_SOCKET_DIR _PATH_SSH_USER_DIR "/agent"
76+
7077
/*
7178
* Per-user file containing host keys of known hosts. This file need not be
7279
* readable by anyone except the user him/herself, though this does not

session.c

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: session.c,v 1.341 2025/04/09 07:00:03 djm Exp $ */
1+
/* $OpenBSD: session.c,v 1.342 2025/05/05 02:48:06 djm Exp $ */
22
/*
33
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
44
* All rights reserved
@@ -175,7 +175,6 @@ static char *auth_info_file = NULL;
175175

176176
/* Name and directory of socket for authentication agent forwarding. */
177177
static char *auth_sock_name = NULL;
178-
static char *auth_sock_dir = NULL;
179178

180179
/* removes the agent forwarding socket */
181180

@@ -185,7 +184,6 @@ auth_sock_cleanup_proc(struct passwd *pw)
185184
if (auth_sock_name != NULL) {
186185
temporarily_use_uid(pw);
187186
unlink(auth_sock_name);
188-
rmdir(auth_sock_dir);
189187
auth_sock_name = NULL;
190188
restore_uid();
191189
}
@@ -205,32 +203,15 @@ auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
205203
/* Temporarily drop privileged uid for mkdir/bind. */
206204
temporarily_use_uid(pw);
207205

208-
/* Allocate a buffer for the socket name, and format the name. */
209-
auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
210-
211-
/* Create private directory for socket */
212-
if (mkdtemp(auth_sock_dir) == NULL) {
206+
if (agent_listener(pw->pw_dir, "sshd", &sock, &auth_sock_name) != 0) {
207+
/* a more detailed error is already logged */
213208
ssh_packet_send_debug(ssh, "Agent forwarding disabled: "
214-
"mkdtemp() failed: %.100s", strerror(errno));
209+
"couldn't create listener socket");
215210
restore_uid();
216-
free(auth_sock_dir);
217-
auth_sock_dir = NULL;
218211
goto authsock_err;
219212
}
220-
221-
xasprintf(&auth_sock_name, "%s/agent.%ld",
222-
auth_sock_dir, (long) getpid());
223-
224-
/* Start a Unix listener on auth_sock_name. */
225-
sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
226-
227-
/* Restore the privileged uid. */
228213
restore_uid();
229214

230-
/* Check for socket/bind/listen failure. */
231-
if (sock < 0)
232-
goto authsock_err;
233-
234215
/* Allocate a channel for the authentication agent socket. */
235216
nc = channel_new(ssh, "auth-listener",
236217
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
@@ -241,16 +222,9 @@ auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
241222

242223
authsock_err:
243224
free(auth_sock_name);
244-
if (auth_sock_dir != NULL) {
245-
temporarily_use_uid(pw);
246-
rmdir(auth_sock_dir);
247-
restore_uid();
248-
free(auth_sock_dir);
249-
}
250225
if (sock != -1)
251226
close(sock);
252227
auth_sock_name = NULL;
253-
auth_sock_dir = NULL;
254228
return 0;
255229
}
256230

ssh-agent.1

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.\" $OpenBSD: ssh-agent.1,v 1.82 2025/02/09 18:24:08 schwarze Exp $
1+
.\" $OpenBSD: ssh-agent.1,v 1.83 2025/05/05 02:48:06 djm Exp $
22
.\"
33
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
44
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,7 +34,7 @@
3434
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3535
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3636
.\"
37-
.Dd $Mdocdate: February 9 2025 $
37+
.Dd $Mdocdate: May 5 2025 $
3838
.Dt SSH-AGENT 1
3939
.Os
4040
.Sh NAME
@@ -43,13 +43,14 @@
4343
.Sh SYNOPSIS
4444
.Nm ssh-agent
4545
.Op Fl c | s
46-
.Op Fl \&Dd
46+
.Op Fl \&DdTU
4747
.Op Fl a Ar bind_address
4848
.Op Fl E Ar fingerprint_hash
4949
.Op Fl O Ar option
5050
.Op Fl P Ar allowed_providers
5151
.Op Fl t Ar life
5252
.Nm ssh-agent
53+
.Op Fl TU
5354
.Op Fl a Ar bind_address
5455
.Op Fl E Ar fingerprint_hash
5556
.Op Fl O Ar option
@@ -59,6 +60,8 @@
5960
.Nm ssh-agent
6061
.Op Fl c | s
6162
.Fl k
63+
.Nm ssh-agent
64+
.Fl u
6265
.Sh DESCRIPTION
6366
.Nm
6467
is a program to hold private keys used for public key authentication.
@@ -74,8 +77,8 @@ Bind the agent to the
7477
.Ux Ns -domain
7578
socket
7679
.Ar bind_address .
77-
The default is
78-
.Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .
80+
The default is to create a socket at a random path matching
81+
.Pa $HOME/.ssh/agent/s.*
7982
.It Fl c
8083
Generate C-shell commands on standard output.
8184
This is the default if
@@ -173,6 +176,11 @@ Generate Bourne shell commands on standard output.
173176
This is the default if
174177
.Ev SHELL
175178
does not look like it's a csh style of shell.
179+
.It Fl T
180+
Bind the agent socket in a randomised subdirectory of the form
181+
.Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt ,
182+
instead of the default behaviour of using a randomised name matching
183+
.Pa $HOME/.ssh/agent/s.* .
176184
.It Fl t Ar life
177185
Set a default value for the maximum lifetime of identities added to the agent.
178186
The lifetime may be specified in seconds or in a time format specified in
@@ -186,6 +194,20 @@ If a command (and optional arguments) is given,
186194
this is executed as a subprocess of the agent.
187195
The agent exits automatically when the command given on the command
188196
line terminates.
197+
.It Fl U
198+
Instructs
199+
.Nm
200+
not to clean up stale agent sockets under
201+
.Pa $HOME/.ssh/agent/ .
202+
.It Fl u
203+
Instructs
204+
.Nm
205+
to only clean up stale agent sockets under
206+
.Pa $HOME/.ssh/agent/
207+
and then exit immediately.
208+
If this option is given twice,
209+
.Nm
210+
will delete stale agent sockets regardless of the host name that created them.
189211
.El
190212
.Pp
191213
There are three main ways to get an agent set up.

0 commit comments

Comments
 (0)