Bug Summary

File:src/usr.bin/ssh/ssh-agent/../ssh-agent.c
Warning:line 1991, column 2
The return value from the call to 'setgid' is not checked. If an error occurs in 'setgid', the following code may execute with unexpected privileges

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ssh-agent.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh-agent/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh-agent/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh-agent/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c
1/* $OpenBSD: ssh-agent.c,v 1.286 2022/01/12 03:30:32 dtucker Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * The authentication agent program.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 *
14 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <sys/types.h>
38#include <sys/time.h>
39#include <sys/queue.h>
40#include <sys/resource.h>
41#include <sys/socket.h>
42#include <sys/stat.h>
43#include <sys/un.h>
44#include <sys/wait.h>
45
46#ifdef WITH_OPENSSL1
47#include <openssl/evp.h>
48#endif
49
50#include <errno(*__errno()).h>
51#include <fcntl.h>
52#include <paths.h>
53#include <poll.h>
54#include <signal.h>
55#include <stdlib.h>
56#include <stdio.h>
57#include <string.h>
58#include <stdarg.h>
59#include <limits.h>
60#include <time.h>
61#include <unistd.h>
62#include <util.h>
63
64#include "xmalloc.h"
65#include "ssh.h"
66#include "ssh2.h"
67#include "sshbuf.h"
68#include "sshkey.h"
69#include "authfd.h"
70#include "compat.h"
71#include "log.h"
72#include "misc.h"
73#include "digest.h"
74#include "ssherr.h"
75#include "match.h"
76#include "msg.h"
77#include "ssherr.h"
78#include "pathnames.h"
79#include "ssh-pkcs11.h"
80#include "sk-api.h"
81#include "myproposal.h"
82
83#ifndef DEFAULT_ALLOWED_PROVIDERS"/usr/lib*/*,/usr/local/lib*/*"
84# define DEFAULT_ALLOWED_PROVIDERS"/usr/lib*/*,/usr/local/lib*/*" "/usr/lib*/*,/usr/local/lib*/*"
85#endif
86
87/* Maximum accepted message length */
88#define AGENT_MAX_LEN(256*1024) (256*1024)
89/* Maximum bytes to read from client socket */
90#define AGENT_RBUF_LEN(4096) (4096)
91/* Maximum number of recorded session IDs/hostkeys per connection */
92#define AGENT_MAX_SESSION_IDS16 16
93/* Maximum size of session ID */
94#define AGENT_MAX_SID_LEN128 128
95/* Maximum number of destination constraints to accept on a key */
96#define AGENT_MAX_DEST_CONSTRAINTS1024 1024
97
98/* XXX store hostkey_sid in a refcounted tree */
99
100typedef enum {
101 AUTH_UNUSED = 0,
102 AUTH_SOCKET = 1,
103 AUTH_CONNECTION = 2,
104} sock_type;
105
106struct hostkey_sid {
107 struct sshkey *key;
108 struct sshbuf *sid;
109 int forwarded;
110};
111
112typedef struct socket_entry {
113 int fd;
114 sock_type type;
115 struct sshbuf *input;
116 struct sshbuf *output;
117 struct sshbuf *request;
118 size_t nsession_ids;
119 struct hostkey_sid *session_ids;
120} SocketEntry;
121
122u_int sockets_alloc = 0;
123SocketEntry *sockets = NULL((void*)0);
124
125typedef struct identity {
126 TAILQ_ENTRY(identity)struct { struct identity *tqe_next; struct identity **tqe_prev
; }
next;
127 struct sshkey *key;
128 char *comment;
129 char *provider;
130 time_t death;
131 u_int confirm;
132 char *sk_provider;
133 struct dest_constraint *dest_constraints;
134 size_t ndest_constraints;
135} Identity;
136
137struct idtable {
138 int nentries;
139 TAILQ_HEAD(idqueue, identity)struct idqueue { struct identity *tqh_first; struct identity *
*tqh_last; }
idlist;
140};
141
142/* private key table */
143struct idtable *idtab;
144
145int max_fd = 0;
146
147/* pid of shell == parent of agent */
148pid_t parent_pid = -1;
149time_t parent_alive_interval = 0;
150
151/* pid of process for which cleanup_socket is applicable */
152pid_t cleanup_pid = 0;
153
154/* pathname and directory for AUTH_SOCKET */
155char socket_name[PATH_MAX1024];
156char socket_dir[PATH_MAX1024];
157
158/* Pattern-list of allowed PKCS#11/Security key paths */
159static char *allowed_providers;
160
161/* locking */
162#define LOCK_SIZE32 32
163#define LOCK_SALT_SIZE16 16
164#define LOCK_ROUNDS1 1
165int locked = 0;
166u_char lock_pwhash[LOCK_SIZE32];
167u_char lock_salt[LOCK_SALT_SIZE16];
168
169extern char *__progname;
170
171/* Default lifetime in seconds (0 == forever) */
172static int lifetime = 0;
173
174static int fingerprint_hash = SSH_FP_HASH_DEFAULT2;
175
176/* Refuse signing of non-SSH messages for web-origin FIDO keys */
177static int restrict_websafe = 1;
178
179static void
180close_socket(SocketEntry *e)
181{
182 size_t i;
183
184 close(e->fd);
185 sshbuf_free(e->input);
186 sshbuf_free(e->output);
187 sshbuf_free(e->request);
188 for (i = 0; i < e->nsession_ids; i++) {
189 sshkey_free(e->session_ids[i].key);
190 sshbuf_free(e->session_ids[i].sid);
191 }
192 free(e->session_ids);
193 memset(e, '\0', sizeof(*e));
194 e->fd = -1;
195 e->type = AUTH_UNUSED;
196}
197
198static void
199idtab_init(void)
200{
201 idtab = xcalloc(1, sizeof(*idtab));
202 TAILQ_INIT(&idtab->idlist)do { (&idtab->idlist)->tqh_first = ((void*)0); (&
idtab->idlist)->tqh_last = &(&idtab->idlist)
->tqh_first; } while (0)
;
203 idtab->nentries = 0;
204}
205
206static void
207free_dest_constraint_hop(struct dest_constraint_hop *dch)
208{
209 u_int i;
210
211 if (dch == NULL((void*)0))
212 return;
213 free(dch->user);
214 free(dch->hostname);
215 for (i = 0; i < dch->nkeys; i++)
216 sshkey_free(dch->keys[i]);
217 free(dch->keys);
218 free(dch->key_is_ca);
219}
220
221static void
222free_dest_constraints(struct dest_constraint *dcs, size_t ndcs)
223{
224 size_t i;
225
226 for (i = 0; i < ndcs; i++) {
227 free_dest_constraint_hop(&dcs[i].from);
228 free_dest_constraint_hop(&dcs[i].to);
229 }
230 free(dcs);
231}
232
233static void
234free_identity(Identity *id)
235{
236 sshkey_free(id->key);
237 free(id->provider);
238 free(id->comment);
239 free(id->sk_provider);
240 free_dest_constraints(id->dest_constraints, id->ndest_constraints);
241 free(id);
242}
243
244/*
245 * Match 'key' against the key/CA list in a destination constraint hop
246 * Returns 0 on success or -1 otherwise.
247 */
248static int
249match_key_hop(const char *tag, const struct sshkey *key,
250 const struct dest_constraint_hop *dch)
251{
252 const char *reason = NULL((void*)0);
253 const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)";
254 u_int i;
255 char *fp;
256
257 if (key == NULL((void*)0))
258 return -1;
259 /* XXX logspam */
260 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT2,
261 SSH_FP_DEFAULT)) == NULL((void*)0))
262 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 262, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
263 debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 264, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s: entering hostname %s, requested key %s %s, %u keys avail"
, tag, hostname, sshkey_type(key), fp, dch->nkeys)
264 tag, hostname, sshkey_type(key), fp, dch->nkeys)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 264, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s: entering hostname %s, requested key %s %s, %u keys avail"
, tag, hostname, sshkey_type(key), fp, dch->nkeys)
;
265 free(fp);
266 for (i = 0; i < dch->nkeys; i++) {
267 if (dch->keys[i] == NULL((void*)0))
268 return -1;
269 /* XXX logspam */
270 if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT2,
271 SSH_FP_DEFAULT)) == NULL((void*)0))
272 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 272, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
273 debug3_f("%s: key %u: %s%s %s", tag, i,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 275, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s: key %u: %s%s %s"
, tag, i, dch->key_is_ca[i] ? "CA " : "", sshkey_type(dch->
keys[i]), fp)
274 dch->key_is_ca[i] ? "CA " : "",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 275, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s: key %u: %s%s %s"
, tag, i, dch->key_is_ca[i] ? "CA " : "", sshkey_type(dch->
keys[i]), fp)
275 sshkey_type(dch->keys[i]), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 275, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s: key %u: %s%s %s"
, tag, i, dch->key_is_ca[i] ? "CA " : "", sshkey_type(dch->
keys[i]), fp)
;
276 free(fp);
277 if (!sshkey_is_cert(key)) {
278 /* plain key */
279 if (dch->key_is_ca[i] ||
280 !sshkey_equal(key, dch->keys[i]))
281 continue;
282 return 0;
283 }
284 /* certificate */
285 if (!dch->key_is_ca[i])
286 continue;
287 if (key->cert == NULL((void*)0) || key->cert->signature_key == NULL((void*)0))
288 return -1; /* shouldn't happen */
289 if (!sshkey_equal(key->cert->signature_key, dch->keys[i]))
290 continue;
291 if (sshkey_cert_check_host(key, hostname, 1,
292 SSH_ALLOWED_CA_SIGALGS"ssh-ed25519," "ecdsa-sha2-nistp256," "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521,"
"sk-ssh-ed25519@openssh.com," "sk-ecdsa-sha2-nistp256@openssh.com,"
"rsa-sha2-512," "rsa-sha2-256"
, &reason) != 0) {
293 debug_f("cert %s / hostname %s rejected: %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 294, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "cert %s / hostname %s rejected: %s"
, key->cert->key_id, hostname, reason)
294 key->cert->key_id, hostname, reason)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 294, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "cert %s / hostname %s rejected: %s"
, key->cert->key_id, hostname, reason)
;
295 continue;
296 }
297 return 0;
298 }
299 return -1;
300}
301
302/* Check destination constraints on an identity against the hostkey/user */
303static int
304permitted_by_dest_constraints(const struct sshkey *fromkey,
305 const struct sshkey *tokey, Identity *id, const char *user,
306 const char **hostnamep)
307{
308 size_t i;
309 struct dest_constraint *d;
310
311 if (hostnamep != NULL((void*)0))
312 *hostnamep = NULL((void*)0);
313 for (i = 0; i < id->ndest_constraints; i++) {
314 d = id->dest_constraints + i;
315 /* XXX remove logspam */
316 debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
317 i, d->from.user ? d->from.user : "",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
318 d->from.user ? "@" : "",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
319 d->from.hostname ? d->from.hostname : "(ORIGIN)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
320 d->from.nkeys,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
321 d->to.user ? d->to.user : "", d->to.user ? "@" : "",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
322 d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 322, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)"
, i, d->from.user ? d->from.user : "", d->from.user ?
"@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)"
, d->from.nkeys, d->to.user ? d->to.user : "", d->
to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)"
, d->to.nkeys)
;
323
324 /* Match 'from' key */
325 if (fromkey == NULL((void*)0)) {
326 /* We are matching the first hop */
327 if (d->from.hostname != NULL((void*)0) || d->from.nkeys != 0)
328 continue;
329 } else if (match_key_hop("from", fromkey, &d->from) != 0)
330 continue;
331
332 /* Match 'to' key */
333 if (tokey != NULL((void*)0) && match_key_hop("to", tokey, &d->to) != 0)
334 continue;
335
336 /* Match user if specified */
337 if (d->to.user != NULL((void*)0) && user != NULL((void*)0) &&
338 !match_pattern(user, d->to.user))
339 continue;
340
341 /* successfully matched this constraint */
342 if (hostnamep != NULL((void*)0))
343 *hostnamep = d->to.hostname;
344 debug2_f("allowed for hostname %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 345, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "allowed for hostname %s"
, d->to.hostname == ((void*)0) ? "*" : d->to.hostname)
345 d->to.hostname == NULL ? "*" : d->to.hostname)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 345, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "allowed for hostname %s"
, d->to.hostname == ((void*)0) ? "*" : d->to.hostname)
;
346 return 0;
347 }
348 /* no match */
349 debug2_f("%s identity \"%s\" not permitted for this destination",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 350, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "%s identity \"%s\" not permitted for this destination"
, sshkey_type(id->key), id->comment)
350 sshkey_type(id->key), id->comment)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 350, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "%s identity \"%s\" not permitted for this destination"
, sshkey_type(id->key), id->comment)
;
351 return -1;
352}
353
354/*
355 * Check whether hostkeys on a SocketEntry and the optionally specified user
356 * are permitted by the destination constraints on the Identity.
357 * Returns 0 on success or -1 otherwise.
358 */
359static int
360identity_permitted(Identity *id, SocketEntry *e, char *user,
361 const char **forward_hostnamep, const char **last_hostnamep)
362{
363 size_t i;
364 const char **hp;
365 struct hostkey_sid *hks;
366 const struct sshkey *fromkey = NULL((void*)0);
367 const char *test_user;
368 char *fp1, *fp2;
369
370 /* XXX remove logspam */
371 debug3_f("entering: key %s comment \"%s\", %zu socket bindings, "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 373, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "entering: key %s comment \"%s\", %zu socket bindings, "
"%zu constraints", sshkey_type(id->key), id->comment, e
->nsession_ids, id->ndest_constraints)
372 "%zu constraints", sshkey_type(id->key), id->comment,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 373, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "entering: key %s comment \"%s\", %zu socket bindings, "
"%zu constraints", sshkey_type(id->key), id->comment, e
->nsession_ids, id->ndest_constraints)
373 e->nsession_ids, id->ndest_constraints)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 373, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "entering: key %s comment \"%s\", %zu socket bindings, "
"%zu constraints", sshkey_type(id->key), id->comment, e
->nsession_ids, id->ndest_constraints)
;
374 if (id->ndest_constraints == 0)
375 return 0; /* unconstrained */
376 if (e->nsession_ids == 0)
377 return 0; /* local use */
378 /*
379 * Walk through the hops recorded by session_id and try to find a
380 * constraint that satisfies each.
381 */
382 for (i = 0; i < e->nsession_ids; i++) {
383 hks = e->session_ids + i;
384 if (hks->key == NULL((void*)0))
385 fatal_f("internal error: no bound key")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 385, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "internal error: no bound key"
)
;
386 /* XXX remove logspam */
387 fp1 = fp2 = NULL((void*)0);
388 if (fromkey != NULL((void*)0) &&
389 (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT2,
390 SSH_FP_DEFAULT)) == NULL((void*)0))
391 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 391, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
392 if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT2,
393 SSH_FP_DEFAULT)) == NULL((void*)0))
394 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 394, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
395 debug3_f("socketentry fd=%d, entry %zu %s, "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
396 "from hostkey %s %s to user %s hostkey %s %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
397 e->fd, i, hks->forwarded ? "FORWARD" : "AUTH",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
398 fromkey ? sshkey_type(fromkey) : "(ORIGIN)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
399 fromkey ? fp1 : "", user ? user : "(ANY)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
400 sshkey_type(hks->key), fp2)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 400, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "socketentry fd=%d, entry %zu %s, "
"from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks
->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey
) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type
(hks->key), fp2)
;
401 free(fp1);
402 free(fp2);
403 /*
404 * Record the hostnames for the initial forwarding and
405 * the final destination.
406 */
407 hp = NULL((void*)0);
408 if (i == e->nsession_ids - 1)
409 hp = last_hostnamep;
410 else if (i == 0)
411 hp = forward_hostnamep;
412 /* Special handling for final recorded binding */
413 test_user = NULL((void*)0);
414 if (i == e->nsession_ids - 1) {
415 /* Can only check user at final hop */
416 test_user = user;
417 /*
418 * user is only presented for signature requests.
419 * If this is the case, make sure last binding is not
420 * for a forwarding.
421 */
422 if (hks->forwarded && user != NULL((void*)0)) {
423 error_f("tried to sign on forwarding hop")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 423, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "tried to sign on forwarding hop"
)
;
424 return -1;
425 }
426 } else if (!hks->forwarded) {
427 error_f("tried to forward though signing bind")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 427, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "tried to forward though signing bind"
)
;
428 return -1;
429 }
430 if (permitted_by_dest_constraints(fromkey, hks->key, id,
431 test_user, hp) != 0)
432 return -1;
433 fromkey = hks->key;
434 }
435 /*
436 * Another special case: if the last bound session ID was for a
437 * forwarding, and this function is not being called to check a sign
438 * request (i.e. no 'user' supplied), then only permit the key if
439 * there is a permission that would allow it to be used at another
440 * destination. This hides keys that are allowed to be used to
441 * authenticate *to* a host but not permitted for *use* beyond it.
442 */
443 hks = &e->session_ids[e->nsession_ids - 1];
444 if (hks->forwarded && user == NULL((void*)0) &&
445 permitted_by_dest_constraints(hks->key, NULL((void*)0), id,
446 NULL((void*)0), NULL((void*)0)) != 0) {
447 debug3_f("key permitted at host but not after")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 447, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "key permitted at host but not after"
)
;
448 return -1;
449 }
450
451 /* success */
452 return 0;
453}
454
455/* return matching private key for given public key */
456static Identity *
457lookup_identity(struct sshkey *key)
458{
459 Identity *id;
460
461 TAILQ_FOREACH(id, &idtab->idlist, next)for((id) = ((&idtab->idlist)->tqh_first); (id) != (
(void*)0); (id) = ((id)->next.tqe_next))
{
462 if (sshkey_equal(key, id->key))
463 return (id);
464 }
465 return (NULL((void*)0));
466}
467
468/* Check confirmation of keysign request */
469static int
470confirm_key(Identity *id, const char *extra)
471{
472 char *p;
473 int ret = -1;
474
475 p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
476 if (p != NULL((void*)0) &&
477 ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
478 id->comment, p,
479 extra == NULL((void*)0) ? "" : "\n", extra == NULL((void*)0) ? "" : extra))
480 ret = 0;
481 free(p);
482
483 return (ret);
484}
485
486static void
487send_status(SocketEntry *e, int success)
488{
489 int r;
490
491 if ((r = sshbuf_put_u32(e->output, 1)) != 0 ||
492 (r = sshbuf_put_u8(e->output, success ?
493 SSH_AGENT_SUCCESS6 : SSH_AGENT_FAILURE5)) != 0)
494 fatal_fr(r, "compose")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 494, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose")
;
495}
496
497/* send list of supported public keys to 'client' */
498static void
499process_request_identities(SocketEntry *e)
500{
501 Identity *id;
502 struct sshbuf *msg, *keys;
503 int r;
504 u_int nentries = 0;
505
506 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 506, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
507
508 if ((msg = sshbuf_new()) == NULL((void*)0) || (keys = sshbuf_new()) == NULL((void*)0))
509 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 509, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
510 TAILQ_FOREACH(id, &idtab->idlist, next)for((id) = ((&idtab->idlist)->tqh_first); (id) != (
(void*)0); (id) = ((id)->next.tqe_next))
{
511 /* identity not visible, don't include in response */
512 if (identity_permitted(id, e, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0)
513 continue;
514 if ((r = sshkey_puts_opts(id->key, keys,
515 SSHKEY_SERIALIZE_INFO)) != 0 ||
516 (r = sshbuf_put_cstring(keys, id->comment)) != 0) {
517 error_fr(r, "compose key/comment")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 517, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "compose key/comment"
)
;
518 continue;
519 }
520 nentries++;
521 }
522 debug2_f("replying with %u allowed of %u available keys",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 523, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "replying with %u allowed of %u available keys"
, nentries, idtab->nentries)
523 nentries, idtab->nentries)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 523, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "replying with %u allowed of %u available keys"
, nentries, idtab->nentries)
;
524 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER12)) != 0 ||
525 (r = sshbuf_put_u32(msg, nentries)) != 0 ||
526 (r = sshbuf_putb(msg, keys)) != 0)
527 fatal_fr(r, "compose")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 527, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose")
;
528 if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
529 fatal_fr(r, "enqueue")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 529, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "enqueue")
;
530 sshbuf_free(msg);
531 sshbuf_free(keys);
532}
533
534
535static char *
536agent_decode_alg(struct sshkey *key, u_int flags)
537{
538 if (key->type == KEY_RSA) {
539 if (flags & SSH_AGENT_RSA_SHA2_2560x02)
540 return "rsa-sha2-256";
541 else if (flags & SSH_AGENT_RSA_SHA2_5120x04)
542 return "rsa-sha2-512";
543 } else if (key->type == KEY_RSA_CERT) {
544 if (flags & SSH_AGENT_RSA_SHA2_2560x02)
545 return "rsa-sha2-256-cert-v01@openssh.com";
546 else if (flags & SSH_AGENT_RSA_SHA2_5120x04)
547 return "rsa-sha2-512-cert-v01@openssh.com";
548 }
549 return NULL((void*)0);
550}
551
552/*
553 * Attempt to parse the contents of a buffer as a SSH publickey userauth
554 * request, checking its contents for consistency and matching the embedded
555 * key against the one that is being used for signing.
556 * Note: does not modify msg buffer.
557 * Optionally extract the username, session ID and/or hostkey from the request.
558 */
559static int
560parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
561 char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp)
562{
563 struct sshbuf *b = NULL((void*)0), *sess_id = NULL((void*)0);
564 char *user = NULL((void*)0), *service = NULL((void*)0), *method = NULL((void*)0), *pkalg = NULL((void*)0);
565 int r;
566 u_char t, sig_follows;
567 struct sshkey *mkey = NULL((void*)0), *hostkey = NULL((void*)0);
568
569 if (userp != NULL((void*)0))
570 *userp = NULL((void*)0);
571 if (sess_idp != NULL((void*)0))
572 *sess_idp = NULL((void*)0);
573 if (hostkeyp != NULL((void*)0))
574 *hostkeyp = NULL((void*)0);
575 if ((b = sshbuf_fromb(msg)) == NULL((void*)0))
576 fatal_f("sshbuf_fromb")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 576, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_fromb")
;
577
578 /* SSH userauth request */
579 if ((r = sshbuf_froms(b, &sess_id)) != 0)
580 goto out;
581 if (sshbuf_len(sess_id) == 0) {
582 r = SSH_ERR_INVALID_FORMAT-4;
583 goto out;
584 }
585 if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
586 (r = sshbuf_get_cstring(b, &user, NULL((void*)0))) != 0 || /* server user */
587 (r = sshbuf_get_cstring(b, &service, NULL((void*)0))) != 0 || /* service */
588 (r = sshbuf_get_cstring(b, &method, NULL((void*)0))) != 0 || /* method */
589 (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */
590 (r = sshbuf_get_cstring(b, &pkalg, NULL((void*)0))) != 0 || /* alg */
591 (r = sshkey_froms(b, &mkey)) != 0) /* key */
592 goto out;
593 if (t != SSH2_MSG_USERAUTH_REQUEST50 ||
594 sig_follows != 1 ||
595 strcmp(service, "ssh-connection") != 0 ||
596 !sshkey_equal(expected_key, mkey) ||
597 sshkey_type_from_name(pkalg) != expected_key->type) {
598 r = SSH_ERR_INVALID_FORMAT-4;
599 goto out;
600 }
601 if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
602 if ((r = sshkey_froms(b, &hostkey)) != 0)
603 goto out;
604 } else if (strcmp(method, "publickey") != 0) {
605 r = SSH_ERR_INVALID_FORMAT-4;
606 goto out;
607 }
608 if (sshbuf_len(b) != 0) {
609 r = SSH_ERR_INVALID_FORMAT-4;
610 goto out;
611 }
612 /* success */
613 r = 0;
614 debug3_f("well formed userauth")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 614, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "well formed userauth"
)
;
615 if (userp != NULL((void*)0)) {
616 *userp = user;
617 user = NULL((void*)0);
618 }
619 if (sess_idp != NULL((void*)0)) {
620 *sess_idp = sess_id;
621 sess_id = NULL((void*)0);
622 }
623 if (hostkeyp != NULL((void*)0)) {
624 *hostkeyp = hostkey;
625 hostkey = NULL((void*)0);
626 }
627 out:
628 sshbuf_free(b);
629 sshbuf_free(sess_id);
630 free(user);
631 free(service);
632 free(method);
633 free(pkalg);
634 sshkey_free(mkey);
635 sshkey_free(hostkey);
636 return r;
637}
638
639/*
640 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
641 * Note: does not modify buffer.
642 */
643static int
644parse_sshsig_request(struct sshbuf *msg)
645{
646 int r;
647 struct sshbuf *b;
648
649 if ((b = sshbuf_fromb(msg)) == NULL((void*)0))
650 fatal_f("sshbuf_fromb")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 650, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_fromb")
;
651
652 if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 ||
653 (r = sshbuf_consume(b, 6)) != 0 ||
654 (r = sshbuf_get_cstring(b, NULL((void*)0), NULL((void*)0))) != 0 || /* namespace */
655 (r = sshbuf_get_string_direct(b, NULL((void*)0), NULL((void*)0))) != 0 || /* reserved */
656 (r = sshbuf_get_cstring(b, NULL((void*)0), NULL((void*)0))) != 0 || /* hashalg */
657 (r = sshbuf_get_string_direct(b, NULL((void*)0), NULL((void*)0))) != 0) /* H(msg) */
658 goto out;
659 if (sshbuf_len(b) != 0) {
660 r = SSH_ERR_INVALID_FORMAT-4;
661 goto out;
662 }
663 /* success */
664 r = 0;
665 out:
666 sshbuf_free(b);
667 return r;
668}
669
670/*
671 * This function inspects a message to be signed by a FIDO key that has a
672 * web-like application string (i.e. one that does not begin with "ssh:".
673 * It checks that the message is one of those expected for SSH operations
674 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
675 * for the web.
676 */
677static int
678check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
679{
680 if (parse_userauth_request(data, key, NULL((void*)0), NULL((void*)0), NULL((void*)0)) == 0) {
681 debug_f("signed data matches public key userauth request")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 681, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "signed data matches public key userauth request"
)
;
682 return 1;
683 }
684 if (parse_sshsig_request(data) == 0) {
685 debug_f("signed data matches SSHSIG signature request")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 685, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "signed data matches SSHSIG signature request"
)
;
686 return 1;
687 }
688
689 /* XXX check CA signature operation */
690
691 error("web-origin key attempting to sign non-SSH message")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 691, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "web-origin key attempting to sign non-SSH message"
)
;
692 return 0;
693}
694
695static int
696buf_equal(const struct sshbuf *a, const struct sshbuf *b)
697{
698 if (sshbuf_ptr(a) == NULL((void*)0) || sshbuf_ptr(b) == NULL((void*)0))
699 return SSH_ERR_INVALID_ARGUMENT-10;
700 if (sshbuf_len(a) != sshbuf_len(b))
701 return SSH_ERR_INVALID_FORMAT-4;
702 if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0)
703 return SSH_ERR_INVALID_FORMAT-4;
704 return 0;
705}
706
707/* ssh2 only */
708static void
709process_sign_request2(SocketEntry *e)
710{
711 u_char *signature = NULL((void*)0);
712 size_t slen = 0;
713 u_int compat = 0, flags;
714 int r, ok = -1;
715 char *fp = NULL((void*)0), *user = NULL((void*)0), *sig_dest = NULL((void*)0);
716 const char *fwd_host = NULL((void*)0), *dest_host = NULL((void*)0);
717 struct sshbuf *msg = NULL((void*)0), *data = NULL((void*)0), *sid = NULL((void*)0);
718 struct sshkey *key = NULL((void*)0), *hostkey = NULL((void*)0);
719 struct identity *id;
720 struct notifier_ctx *notifier = NULL((void*)0);
721
722 debug_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 722, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "entering")
;
723
724 if ((msg = sshbuf_new()) == NULL((void*)0) || (data = sshbuf_new()) == NULL((void*)0))
725 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 725, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
726 if ((r = sshkey_froms(e->request, &key)) != 0 ||
727 (r = sshbuf_get_stringb(e->request, data)) != 0 ||
728 (r = sshbuf_get_u32(e->request, &flags)) != 0) {
729 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 729, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
730 goto send;
731 }
732
733 if ((id = lookup_identity(key)) == NULL((void*)0)) {
734 verbose_f("%s key not found", sshkey_type(key))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 734, 1, SYSLOG_LEVEL_VERBOSE, ((void*)0), "%s key not found"
, sshkey_type(key))
;
735 goto send;
736 }
737 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT2,
738 SSH_FP_DEFAULT)) == NULL((void*)0))
739 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 739, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
740
741 if (id->ndest_constraints != 0) {
742 if (e->nsession_ids == 0) {
743 logit_f("refusing use of destination-constrained key "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 744, 1, SYSLOG_LEVEL_INFO, ((void*)0), "refusing use of destination-constrained key "
"to sign on unbound connection")
744 "to sign on unbound connection")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 744, 1, SYSLOG_LEVEL_INFO, ((void*)0), "refusing use of destination-constrained key "
"to sign on unbound connection")
;
745 goto send;
746 }
747 if (parse_userauth_request(data, key, &user, &sid,
748 &hostkey) != 0) {
749 logit_f("refusing use of destination-constrained key "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 750, 1, SYSLOG_LEVEL_INFO, ((void*)0), "refusing use of destination-constrained key "
"to sign an unidentified signature")
750 "to sign an unidentified signature")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 750, 1, SYSLOG_LEVEL_INFO, ((void*)0), "refusing use of destination-constrained key "
"to sign an unidentified signature")
;
751 goto send;
752 }
753 /* XXX logspam */
754 debug_f("user=%s", user)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 754, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "user=%s", user)
;
755 if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0)
756 goto send;
757 /* XXX display fwd_host/dest_host in askpass UI */
758 /*
759 * Ensure that the session ID is the most recent one
760 * registered on the socket - it should have been bound by
761 * ssh immediately before userauth.
762 */
763 if (buf_equal(sid,
764 e->session_ids[e->nsession_ids - 1].sid) != 0) {
765 error_f("unexpected session ID (%zu listed) on "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 768, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unexpected session ID (%zu listed) on "
"signature request for target user %s with " "key %s %s", e->
nsession_ids, user, sshkey_type(id->key), fp)
766 "signature request for target user %s with "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 768, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unexpected session ID (%zu listed) on "
"signature request for target user %s with " "key %s %s", e->
nsession_ids, user, sshkey_type(id->key), fp)
767 "key %s %s", e->nsession_ids, user,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 768, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unexpected session ID (%zu listed) on "
"signature request for target user %s with " "key %s %s", e->
nsession_ids, user, sshkey_type(id->key), fp)
768 sshkey_type(id->key), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 768, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unexpected session ID (%zu listed) on "
"signature request for target user %s with " "key %s %s", e->
nsession_ids, user, sshkey_type(id->key), fp)
;
769 goto send;
770 }
771 /*
772 * Ensure that the hostkey embedded in the signature matches
773 * the one most recently bound to the socket. An exception is
774 * made for the initial forwarding hop.
775 */
776 if (e->nsession_ids > 1 && hostkey == NULL((void*)0)) {
777 error_f("refusing use of destination-constrained key: "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 779, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"no hostkey recorded in signature for forwarded " "connection"
)
778 "no hostkey recorded in signature for forwarded "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 779, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"no hostkey recorded in signature for forwarded " "connection"
)
779 "connection")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 779, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"no hostkey recorded in signature for forwarded " "connection"
)
;
780 goto send;
781 }
782 if (hostkey != NULL((void*)0) && !sshkey_equal(hostkey,
783 e->session_ids[e->nsession_ids - 1].key)) {
784 error_f("refusing use of destination-constrained key: "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 786, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"mismatch between hostkey in request and most " "recently bound session"
)
785 "mismatch between hostkey in request and most "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 786, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"mismatch between hostkey in request and most " "recently bound session"
)
786 "recently bound session")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 786, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "refusing use of destination-constrained key: "
"mismatch between hostkey in request and most " "recently bound session"
)
;
787 goto send;
788 }
789 xasprintf(&sig_dest, "public key authentication request for "
790 "user \"%s\" to listed host", user);
791 }
792 if (id->confirm && confirm_key(id, sig_dest) != 0) {
793 verbose_f("user refused key")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 793, 1, SYSLOG_LEVEL_VERBOSE, ((void*)0), "user refused key"
)
;
794 goto send;
795 }
796 if (sshkey_is_sk(id->key)) {
797 if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
798 !check_websafe_message_contents(key, data)) {
799 /* error already logged */
800 goto send;
801 }
802 if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD0x01)) {
803 notifier = notify_start(0,
804 "Confirm user presence for key %s %s%s%s",
805 sshkey_type(id->key), fp,
806 sig_dest == NULL((void*)0) ? "" : "\n",
807 sig_dest == NULL((void*)0) ? "" : sig_dest);
808 }
809 }
810 /* XXX support PIN required FIDO keys */
811 if ((r = sshkey_sign(id->key, &signature, &slen,
812 sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags),
813 id->sk_provider, NULL((void*)0), compat)) != 0) {
814 error_fr(r, "sshkey_sign")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 814, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshkey_sign")
;
815 goto send;
816 }
817 /* Success */
818 ok = 0;
819 send:
820 notify_complete(notifier, "User presence confirmed");
821
822 if (ok == 0) {
823 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE14)) != 0 ||
824 (r = sshbuf_put_string(msg, signature, slen)) != 0)
825 fatal_fr(r, "compose")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 825, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose")
;
826 } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE5)) != 0)
827 fatal_fr(r, "compose failure")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 827, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose failure")
;
828
829 if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
830 fatal_fr(r, "enqueue")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 830, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "enqueue")
;
831
832 sshbuf_free(sid);
833 sshbuf_free(data);
834 sshbuf_free(msg);
835 sshkey_free(key);
836 sshkey_free(hostkey);
837 free(fp);
838 free(signature);
839 free(sig_dest);
840 free(user);
841}
842
843/* shared */
844static void
845process_remove_identity(SocketEntry *e)
846{
847 int r, success = 0;
848 struct sshkey *key = NULL((void*)0);
849 Identity *id;
850
851 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 851, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
852 if ((r = sshkey_froms(e->request, &key)) != 0) {
853 error_fr(r, "parse key")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 853, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse key")
;
854 goto done;
855 }
856 if ((id = lookup_identity(key)) == NULL((void*)0)) {
857 debug_f("key not found")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 857, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "key not found")
;
858 goto done;
859 }
860 /* identity not visible, cannot be removed */
861 if (identity_permitted(id, e, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0)
862 goto done; /* error already logged */
863 /* We have this key, free it. */
864 if (idtab->nentries < 1)
865 fatal_f("internal error: nentries %d", idtab->nentries)sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 865, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "internal error: nentries %d"
, idtab->nentries)
;
866 TAILQ_REMOVE(&idtab->idlist, id, next)do { if (((id)->next.tqe_next) != ((void*)0)) (id)->next
.tqe_next->next.tqe_prev = (id)->next.tqe_prev; else (&
idtab->idlist)->tqh_last = (id)->next.tqe_prev; *(id
)->next.tqe_prev = (id)->next.tqe_next; ; ; } while (0)
;
867 free_identity(id);
868 idtab->nentries--;
869 success = 1;
870 done:
871 sshkey_free(key);
872 send_status(e, success);
873}
874
875static void
876process_remove_all_identities(SocketEntry *e)
877{
878 Identity *id;
879
880 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 880, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
881 /* Loop over all identities and clear the keys. */
882 for (id = TAILQ_FIRST(&idtab->idlist)((&idtab->idlist)->tqh_first); id;
883 id = TAILQ_FIRST(&idtab->idlist)((&idtab->idlist)->tqh_first)) {
884 TAILQ_REMOVE(&idtab->idlist, id, next)do { if (((id)->next.tqe_next) != ((void*)0)) (id)->next
.tqe_next->next.tqe_prev = (id)->next.tqe_prev; else (&
idtab->idlist)->tqh_last = (id)->next.tqe_prev; *(id
)->next.tqe_prev = (id)->next.tqe_next; ; ; } while (0)
;
885 free_identity(id);
886 }
887
888 /* Mark that there are no identities. */
889 idtab->nentries = 0;
890
891 /* Send success. */
892 send_status(e, 1);
893}
894
895/* removes expired keys and returns number of seconds until the next expiry */
896static time_t
897reaper(void)
898{
899 time_t deadline = 0, now = monotime();
900 Identity *id, *nxt;
901
902 for (id = TAILQ_FIRST(&idtab->idlist)((&idtab->idlist)->tqh_first); id; id = nxt) {
903 nxt = TAILQ_NEXT(id, next)((id)->next.tqe_next);
904 if (id->death == 0)
905 continue;
906 if (now >= id->death) {
907 debug("expiring key '%s'", id->comment)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 907, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "expiring key '%s'"
, id->comment)
;
908 TAILQ_REMOVE(&idtab->idlist, id, next)do { if (((id)->next.tqe_next) != ((void*)0)) (id)->next
.tqe_next->next.tqe_prev = (id)->next.tqe_prev; else (&
idtab->idlist)->tqh_last = (id)->next.tqe_prev; *(id
)->next.tqe_prev = (id)->next.tqe_next; ; ; } while (0)
;
909 free_identity(id);
910 idtab->nentries--;
911 } else
912 deadline = (deadline == 0) ? id->death :
913 MINIMUM(deadline, id->death)(((deadline) < (id->death)) ? (deadline) : (id->death
))
;
914 }
915 if (deadline == 0 || deadline <= now)
916 return 0;
917 else
918 return (deadline - now);
919}
920
921static int
922parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch)
923{
924 u_char key_is_ca;
925 size_t elen = 0;
926 int r;
927 struct sshkey *k = NULL((void*)0);
928 char *fp;
929
930 memset(dch, '\0', sizeof(*dch));
931 if ((r = sshbuf_get_cstring(b, &dch->user, NULL((void*)0))) != 0 ||
932 (r = sshbuf_get_cstring(b, &dch->hostname, NULL((void*)0))) != 0 ||
933 (r = sshbuf_get_string_direct(b, NULL((void*)0), &elen)) != 0) {
934 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 934, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
935 goto out;
936 }
937 if (elen != 0) {
938 error_f("unsupported extensions (len %zu)", elen)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 938, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unsupported extensions (len %zu)"
, elen)
;
939 r = SSH_ERR_FEATURE_UNSUPPORTED-59;
940 goto out;
941 }
942 if (*dch->hostname == '\0') {
943 free(dch->hostname);
944 dch->hostname = NULL((void*)0);
945 }
946 if (*dch->user == '\0') {
947 free(dch->user);
948 dch->user = NULL((void*)0);
949 }
950 while (sshbuf_len(b) != 0) {
951 dch->keys = xrecallocarray(dch->keys, dch->nkeys,
952 dch->nkeys + 1, sizeof(*dch->keys));
953 dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys,
954 dch->nkeys + 1, sizeof(*dch->key_is_ca));
955 if ((r = sshkey_froms(b, &k)) != 0 ||
956 (r = sshbuf_get_u8(b, &key_is_ca)) != 0)
957 goto out;
958 if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT2,
959 SSH_FP_DEFAULT)) == NULL((void*)0))
960 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 960, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
961 debug3_f("%s%s%s: adding %skey %s %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 964, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s%s%s: adding %skey %s %s"
, dch->user == ((void*)0) ? "" : dch->user, dch->user
== ((void*)0) ? "" : "@", dch->hostname, key_is_ca ? "CA "
: "", sshkey_type(k), fp)
962 dch->user == NULL ? "" : dch->user,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 964, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s%s%s: adding %skey %s %s"
, dch->user == ((void*)0) ? "" : dch->user, dch->user
== ((void*)0) ? "" : "@", dch->hostname, key_is_ca ? "CA "
: "", sshkey_type(k), fp)
963 dch->user == NULL ? "" : "@",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 964, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s%s%s: adding %skey %s %s"
, dch->user == ((void*)0) ? "" : dch->user, dch->user
== ((void*)0) ? "" : "@", dch->hostname, key_is_ca ? "CA "
: "", sshkey_type(k), fp)
964 dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 964, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s%s%s: adding %skey %s %s"
, dch->user == ((void*)0) ? "" : dch->user, dch->user
== ((void*)0) ? "" : "@", dch->hostname, key_is_ca ? "CA "
: "", sshkey_type(k), fp)
;
965 free(fp);
966 dch->keys[dch->nkeys] = k;
967 dch->key_is_ca[dch->nkeys] = key_is_ca != 0;
968 dch->nkeys++;
969 k = NULL((void*)0); /* transferred */
970 }
971 /* success */
972 r = 0;
973 out:
974 sshkey_free(k);
975 return r;
976}
977
978static int
979parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc)
980{
981 struct sshbuf *b = NULL((void*)0), *frombuf = NULL((void*)0), *tobuf = NULL((void*)0);
982 int r;
983 size_t elen = 0;
984
985 debug3_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 985, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "entering")
;
986
987 memset(dc, '\0', sizeof(*dc));
988 if ((r = sshbuf_froms(m, &b)) != 0 ||
989 (r = sshbuf_froms(b, &frombuf)) != 0 ||
990 (r = sshbuf_froms(b, &tobuf)) != 0 ||
991 (r = sshbuf_get_string_direct(b, NULL((void*)0), &elen)) != 0) {
992 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 992, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
993 goto out;
994 }
995 if ((r = parse_dest_constraint_hop(frombuf, &dc->from) != 0) ||
996 (r = parse_dest_constraint_hop(tobuf, &dc->to) != 0))
997 goto out; /* already logged */
998 if (elen != 0) {
999 error_f("unsupported extensions (len %zu)", elen)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 999, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unsupported extensions (len %zu)"
, elen)
;
1000 r = SSH_ERR_FEATURE_UNSUPPORTED-59;
1001 goto out;
1002 }
1003 debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1006, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "parsed %s (%u keys) > %s%s%s (%u keys)"
, dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc
->from.nkeys, dc->to.user ? dc->to.user : "", dc->
to.user ? "@" : "", dc->to.hostname ? dc->to.hostname :
"(ANY)", dc->to.nkeys)
1004 dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1006, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "parsed %s (%u keys) > %s%s%s (%u keys)"
, dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc
->from.nkeys, dc->to.user ? dc->to.user : "", dc->
to.user ? "@" : "", dc->to.hostname ? dc->to.hostname :
"(ANY)", dc->to.nkeys)
1005 dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1006, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "parsed %s (%u keys) > %s%s%s (%u keys)"
, dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc
->from.nkeys, dc->to.user ? dc->to.user : "", dc->
to.user ? "@" : "", dc->to.hostname ? dc->to.hostname :
"(ANY)", dc->to.nkeys)
1006 dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1006, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "parsed %s (%u keys) > %s%s%s (%u keys)"
, dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc
->from.nkeys, dc->to.user ? dc->to.user : "", dc->
to.user ? "@" : "", dc->to.hostname ? dc->to.hostname :
"(ANY)", dc->to.nkeys)
;
1007 /* check consistency */
1008 if ((dc->from.hostname == NULL((void*)0)) != (dc->from.nkeys == 0) ||
1009 dc->from.user != NULL((void*)0)) {
1010 error_f("inconsistent \"from\" specification")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1010, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "inconsistent \"from\" specification"
)
;
1011 r = SSH_ERR_INVALID_FORMAT-4;
1012 goto out;
1013 }
1014 if (dc->to.hostname == NULL((void*)0) || dc->to.nkeys == 0) {
1015 error_f("incomplete \"to\" specification")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1015, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "incomplete \"to\" specification"
)
;
1016 r = SSH_ERR_INVALID_FORMAT-4;
1017 goto out;
1018 }
1019 /* success */
1020 r = 0;
1021 out:
1022 sshbuf_free(b);
1023 sshbuf_free(frombuf);
1024 sshbuf_free(tobuf);
1025 return r;
1026}
1027
1028static int
1029parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
1030 struct dest_constraint **dcsp, size_t *ndcsp)
1031{
1032 char *ext_name = NULL((void*)0);
1033 int r;
1034 struct sshbuf *b = NULL((void*)0);
1035
1036 if ((r = sshbuf_get_cstring(m, &ext_name, NULL((void*)0))) != 0) {
1037 error_fr(r, "parse constraint extension")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1037, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse constraint extension"
)
;
1038 goto out;
1039 }
1040 debug_f("constraint ext %s", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1040, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "constraint ext %s"
, ext_name)
;
1041 if (strcmp(ext_name, "sk-provider@openssh.com") == 0) {
1042 if (sk_providerp == NULL((void*)0)) {
1043 error_f("%s not valid here", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1043, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "%s not valid here"
, ext_name)
;
1044 r = SSH_ERR_INVALID_FORMAT-4;
1045 goto out;
1046 }
1047 if (*sk_providerp != NULL((void*)0)) {
1048 error_f("%s already set", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1048, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "%s already set", ext_name
)
;
1049 r = SSH_ERR_INVALID_FORMAT-4;
1050 goto out;
1051 }
1052 if ((r = sshbuf_get_cstring(m, sk_providerp, NULL((void*)0))) != 0) {
1053 error_fr(r, "parse %s", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1053, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse %s", ext_name
)
;
1054 goto out;
1055 }
1056 } else if (strcmp(ext_name,
1057 "restrict-destination-v00@openssh.com") == 0) {
1058 if (*dcsp != NULL((void*)0)) {
1059 error_f("%s already set", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1059, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "%s already set", ext_name
)
;
1060 goto out;
1061 }
1062 if ((r = sshbuf_froms(m, &b)) != 0) {
1063 error_fr(r, "parse %s outer", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1063, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse %s outer", ext_name
)
;
1064 goto out;
1065 }
1066 while (sshbuf_len(b) != 0) {
1067 if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS1024) {
1068 error_f("too many %s constraints", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1068, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "too many %s constraints"
, ext_name)
;
1069 goto out;
1070 }
1071 *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1,
1072 sizeof(**dcsp));
1073 if ((r = parse_dest_constraint(b,
1074 *dcsp + (*ndcsp)++)) != 0)
1075 goto out; /* error already logged */
1076 }
1077 } else {
1078 error_f("unsupported constraint \"%s\"", ext_name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1078, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "unsupported constraint \"%s\""
, ext_name)
;
1079 r = SSH_ERR_FEATURE_UNSUPPORTED-59;
1080 goto out;
1081 }
1082 /* success */
1083 r = 0;
1084 out:
1085 free(ext_name);
1086 sshbuf_free(b);
1087 return r;
1088}
1089
1090static int
1091parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp,
1092 u_int *secondsp, int *confirmp, char **sk_providerp,
1093 struct dest_constraint **dcsp, size_t *ndcsp)
1094{
1095 u_char ctype;
1096 int r;
1097 u_int seconds, maxsign = 0;
1098
1099 while (sshbuf_len(m)) {
1100 if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
1101 error_fr(r, "parse constraint type")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1101, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse constraint type"
)
;
1102 goto out;
1103 }
1104 switch (ctype) {
1105 case SSH_AGENT_CONSTRAIN_LIFETIME1:
1106 if (*deathp != 0) {
1107 error_f("lifetime already set")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1107, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "lifetime already set"
)
;
1108 r = SSH_ERR_INVALID_FORMAT-4;
1109 goto out;
1110 }
1111 if ((r = sshbuf_get_u32(m, &seconds)) != 0) {
1112 error_fr(r, "parse lifetime constraint")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1112, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse lifetime constraint"
)
;
1113 goto out;
1114 }
1115 *deathp = monotime() + seconds;
1116 *secondsp = seconds;
1117 break;
1118 case SSH_AGENT_CONSTRAIN_CONFIRM2:
1119 if (*confirmp != 0) {
1120 error_f("confirm already set")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1120, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "confirm already set"
)
;
1121 r = SSH_ERR_INVALID_FORMAT-4;
1122 goto out;
1123 }
1124 *confirmp = 1;
1125 break;
1126 case SSH_AGENT_CONSTRAIN_MAXSIGN3:
1127 if (k == NULL((void*)0)) {
1128 error_f("maxsign not valid here")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1128, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "maxsign not valid here"
)
;
1129 r = SSH_ERR_INVALID_FORMAT-4;
1130 goto out;
1131 }
1132 if (maxsign != 0) {
1133 error_f("maxsign already set")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1133, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "maxsign already set"
)
;
1134 r = SSH_ERR_INVALID_FORMAT-4;
1135 goto out;
1136 }
1137 if ((r = sshbuf_get_u32(m, &maxsign)) != 0) {
1138 error_fr(r, "parse maxsign constraint")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1138, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse maxsign constraint"
)
;
1139 goto out;
1140 }
1141 if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
1142 error_fr(r, "enable maxsign")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1142, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "enable maxsign")
;
1143 goto out;
1144 }
1145 break;
1146 case SSH_AGENT_CONSTRAIN_EXTENSION255:
1147 if ((r = parse_key_constraint_extension(m,
1148 sk_providerp, dcsp, ndcsp)) != 0)
1149 goto out; /* error already logged */
1150 break;
1151 default:
1152 error_f("Unknown constraint %d", ctype)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1152, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "Unknown constraint %d"
, ctype)
;
1153 r = SSH_ERR_FEATURE_UNSUPPORTED-59;
1154 goto out;
1155 }
1156 }
1157 /* success */
1158 r = 0;
1159 out:
1160 return r;
1161}
1162
1163static void
1164process_add_identity(SocketEntry *e)
1165{
1166 Identity *id;
1167 int success = 0, confirm = 0;
1168 char *fp, *comment = NULL((void*)0), *sk_provider = NULL((void*)0);
1169 char canonical_provider[PATH_MAX1024];
1170 time_t death = 0;
1171 u_int seconds = 0;
1172 struct dest_constraint *dest_constraints = NULL((void*)0);
1173 size_t ndest_constraints = 0;
1174 struct sshkey *k = NULL((void*)0);
1175 int r = SSH_ERR_INTERNAL_ERROR-1;
1176
1177 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1177, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1178 if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
1179 k == NULL((void*)0) ||
1180 (r = sshbuf_get_cstring(e->request, &comment, NULL((void*)0))) != 0) {
1181 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1181, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1182 goto out;
1183 }
1184 if (parse_key_constraints(e->request, k, &death, &seconds, &confirm,
1185 &sk_provider, &dest_constraints, &ndest_constraints) != 0) {
1186 error_f("failed to parse constraints")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1186, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "failed to parse constraints"
)
;
1187 sshbuf_reset(e->request);
1188 goto out;
1189 }
1190
1191 if (sk_provider != NULL((void*)0)) {
1192 if (!sshkey_is_sk(k)) {
1193 error("Cannot add provider: %s is not an "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1194, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot add provider: %s is not an "
"authenticator-hosted key", sshkey_type(k))
1194 "authenticator-hosted key", sshkey_type(k))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1194, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot add provider: %s is not an "
"authenticator-hosted key", sshkey_type(k))
;
1195 goto out;
1196 }
1197 if (strcasecmp(sk_provider, "internal") == 0) {
1198 debug_f("internal provider")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1198, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "internal provider"
)
;
1199 } else {
1200 if (realpath(sk_provider, canonical_provider) == NULL((void*)0)) {
1201 verbose("failed provider \"%.100s\": "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1203, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed provider \"%.100s\": "
"realpath: %s", sk_provider, strerror((*__errno())))
1202 "realpath: %s", sk_provider,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1203, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed provider \"%.100s\": "
"realpath: %s", sk_provider, strerror((*__errno())))
1203 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1203, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed provider \"%.100s\": "
"realpath: %s", sk_provider, strerror((*__errno())))
;
1204 goto out;
1205 }
1206 free(sk_provider);
1207 sk_provider = xstrdup(canonical_provider);
1208 if (match_pattern_list(sk_provider,
1209 allowed_providers, 0) != 1) {
1210 error("Refusing add key: "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1211, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Refusing add key: "
"provider %s not allowed", sk_provider)
1211 "provider %s not allowed", sk_provider)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1211, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Refusing add key: "
"provider %s not allowed", sk_provider)
;
1212 goto out;
1213 }
1214 }
1215 }
1216 if ((r = sshkey_shield_private(k)) != 0) {
1217 error_fr(r, "shield private")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1217, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "shield private")
;
1218 goto out;
1219 }
1220 if (lifetime && !death)
1221 death = monotime() + lifetime;
1222 if ((id = lookup_identity(k)) == NULL((void*)0)) {
1223 id = xcalloc(1, sizeof(Identity));
1224 TAILQ_INSERT_TAIL(&idtab->idlist, id, next)do { (id)->next.tqe_next = ((void*)0); (id)->next.tqe_prev
= (&idtab->idlist)->tqh_last; *(&idtab->idlist
)->tqh_last = (id); (&idtab->idlist)->tqh_last =
&(id)->next.tqe_next; } while (0)
;
1225 /* Increment the number of identities. */
1226 idtab->nentries++;
1227 } else {
1228 /* identity not visible, do not update */
1229 if (identity_permitted(id, e, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0)
1230 goto out; /* error already logged */
1231 /* key state might have been updated */
1232 sshkey_free(id->key);
1233 free(id->comment);
1234 free(id->sk_provider);
1235 free_dest_constraints(id->dest_constraints,
1236 id->ndest_constraints);
1237 }
1238 /* success */
1239 id->key = k;
1240 id->comment = comment;
1241 id->death = death;
1242 id->confirm = confirm;
1243 id->sk_provider = sk_provider;
1244 id->dest_constraints = dest_constraints;
1245 id->ndest_constraints = ndest_constraints;
1246
1247 if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT2,
1248 SSH_FP_DEFAULT)) == NULL((void*)0))
1249 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1249, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
1250 debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1253, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "add %s %s \"%.100s\" (life: %u) (confirm: %u) "
"(provider: %s) (destination constraints: %zu)", sshkey_ssh_name
(k), fp, comment, seconds, confirm, sk_provider == ((void*)0)
? "none" : sk_provider, ndest_constraints)
1251 "(provider: %s) (destination constraints: %zu)",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1253, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "add %s %s \"%.100s\" (life: %u) (confirm: %u) "
"(provider: %s) (destination constraints: %zu)", sshkey_ssh_name
(k), fp, comment, seconds, confirm, sk_provider == ((void*)0)
? "none" : sk_provider, ndest_constraints)
1252 sshkey_ssh_name(k), fp, comment, seconds, confirm,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1253, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "add %s %s \"%.100s\" (life: %u) (confirm: %u) "
"(provider: %s) (destination constraints: %zu)", sshkey_ssh_name
(k), fp, comment, seconds, confirm, sk_provider == ((void*)0)
? "none" : sk_provider, ndest_constraints)
1253 sk_provider == NULL ? "none" : sk_provider, ndest_constraints)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1253, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "add %s %s \"%.100s\" (life: %u) (confirm: %u) "
"(provider: %s) (destination constraints: %zu)", sshkey_ssh_name
(k), fp, comment, seconds, confirm, sk_provider == ((void*)0)
? "none" : sk_provider, ndest_constraints)
;
1254 free(fp);
1255 /* transferred */
1256 k = NULL((void*)0);
1257 comment = NULL((void*)0);
1258 sk_provider = NULL((void*)0);
1259 dest_constraints = NULL((void*)0);
1260 ndest_constraints = 0;
1261 success = 1;
1262 out:
1263 free(sk_provider);
1264 free(comment);
1265 sshkey_free(k);
1266 free_dest_constraints(dest_constraints, ndest_constraints);
1267 send_status(e, success);
1268}
1269
1270/* XXX todo: encrypt sensitive data with passphrase */
1271static void
1272process_lock_agent(SocketEntry *e, int lock)
1273{
1274 int r, success = 0, delay;
1275 char *passwd;
1276 u_char passwdhash[LOCK_SIZE32];
1277 static u_int fail_count = 0;
1278 size_t pwlen;
1279
1280 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1280, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1281 /*
1282 * This is deliberately fatal: the user has requested that we lock,
1283 * but we can't parse their request properly. The only safe thing to
1284 * do is abort.
1285 */
1286 if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
1287 fatal_fr(r, "parse")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1287, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse")
;
1288 if (pwlen == 0) {
1289 debug("empty password not supported")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1289, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "empty password not supported"
)
;
1290 } else if (locked && !lock) {
1291 if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
1292 passwdhash, sizeof(passwdhash), LOCK_ROUNDS1) < 0)
1293 fatal("bcrypt_pbkdf")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1293, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "bcrypt_pbkdf")
;
1294 if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE32) == 0) {
1295 debug("agent unlocked")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1295, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "agent unlocked")
;
1296 locked = 0;
1297 fail_count = 0;
1298 explicit_bzero(lock_pwhash, sizeof(lock_pwhash));
1299 success = 1;
1300 } else {
1301 /* delay in 0.1s increments up to 10s */
1302 if (fail_count < 100)
1303 fail_count++;
1304 delay = 100000 * fail_count;
1305 debug("unlock failed, delaying %0.1lf seconds",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1306, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "unlock failed, delaying %0.1lf seconds"
, (double)delay/1000000)
1306 (double)delay/1000000)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1306, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "unlock failed, delaying %0.1lf seconds"
, (double)delay/1000000)
;
1307 usleep(delay);
1308 }
1309 explicit_bzero(passwdhash, sizeof(passwdhash));
1310 } else if (!locked && lock) {
1311 debug("agent locked")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1311, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "agent locked")
;
1312 locked = 1;
1313 arc4random_buf(lock_salt, sizeof(lock_salt));
1314 if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
1315 lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS1) < 0)
1316 fatal("bcrypt_pbkdf")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1316, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "bcrypt_pbkdf")
;
1317 success = 1;
1318 }
1319 freezero(passwd, pwlen);
1320 send_status(e, success);
1321}
1322
1323static void
1324no_identities(SocketEntry *e)
1325{
1326 struct sshbuf *msg;
1327 int r;
1328
1329 if ((msg = sshbuf_new()) == NULL((void*)0))
1330 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1330, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
1331 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER12)) != 0 ||
1332 (r = sshbuf_put_u32(msg, 0)) != 0 ||
1333 (r = sshbuf_put_stringb(e->output, msg)) != 0)
1334 fatal_fr(r, "compose")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1334, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose")
;
1335 sshbuf_free(msg);
1336}
1337
1338#ifdef ENABLE_PKCS111
1339static void
1340process_add_smartcard_key(SocketEntry *e)
1341{
1342 char *provider = NULL((void*)0), *pin = NULL((void*)0), canonical_provider[PATH_MAX1024];
1343 char **comments = NULL((void*)0);
1344 int r, i, count = 0, success = 0, confirm = 0;
1345 u_int seconds = 0;
1346 time_t death = 0;
1347 struct sshkey **keys = NULL((void*)0), *k;
1348 Identity *id;
1349 struct dest_constraint *dest_constraints = NULL((void*)0);
1350 size_t ndest_constraints = 0;
1351
1352 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1352, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1353 if ((r = sshbuf_get_cstring(e->request, &provider, NULL((void*)0))) != 0 ||
1354 (r = sshbuf_get_cstring(e->request, &pin, NULL((void*)0))) != 0) {
1355 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1355, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1356 goto send;
1357 }
1358 if (parse_key_constraints(e->request, NULL((void*)0), &death, &seconds, &confirm,
1359 NULL((void*)0), &dest_constraints, &ndest_constraints) != 0) {
1360 error_f("failed to parse constraints")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1360, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "failed to parse constraints"
)
;
1361 goto send;
1362 }
1363 if (realpath(provider, canonical_provider) == NULL((void*)0)) {
1364 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1365, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed PKCS#11 add of \"%.100s\": realpath: %s"
, provider, strerror((*__errno())))
1365 provider, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1365, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed PKCS#11 add of \"%.100s\": realpath: %s"
, provider, strerror((*__errno())))
;
1366 goto send;
1367 }
1368 if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) {
1369 verbose("refusing PKCS#11 add of \"%.100s\": "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1370, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "refusing PKCS#11 add of \"%.100s\": "
"provider not allowed", canonical_provider)
1370 "provider not allowed", canonical_provider)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1370, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "refusing PKCS#11 add of \"%.100s\": "
"provider not allowed", canonical_provider)
;
1371 goto send;
1372 }
1373 debug_f("add %.100s", canonical_provider)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1373, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "add %.100s", canonical_provider
)
;
1374 if (lifetime && !death)
1375 death = monotime() + lifetime;
1376
1377 count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments);
1378 for (i = 0; i < count; i++) {
1379 k = keys[i];
1380 if (lookup_identity(k) == NULL((void*)0)) {
1381 id = xcalloc(1, sizeof(Identity));
1382 id->key = k;
1383 keys[i] = NULL((void*)0); /* transferred */
1384 id->provider = xstrdup(canonical_provider);
1385 if (*comments[i] != '\0') {
1386 id->comment = comments[i];
1387 comments[i] = NULL((void*)0); /* transferred */
1388 } else {
1389 id->comment = xstrdup(canonical_provider);
1390 }
1391 id->death = death;
1392 id->confirm = confirm;
1393 id->dest_constraints = dest_constraints;
1394 id->ndest_constraints = ndest_constraints;
1395 dest_constraints = NULL((void*)0); /* transferred */
1396 ndest_constraints = 0;
1397 TAILQ_INSERT_TAIL(&idtab->idlist, id, next)do { (id)->next.tqe_next = ((void*)0); (id)->next.tqe_prev
= (&idtab->idlist)->tqh_last; *(&idtab->idlist
)->tqh_last = (id); (&idtab->idlist)->tqh_last =
&(id)->next.tqe_next; } while (0)
;
1398 idtab->nentries++;
1399 success = 1;
1400 }
1401 /* XXX update constraints for existing keys */
1402 sshkey_free(keys[i]);
1403 free(comments[i]);
1404 }
1405send:
1406 free(pin);
1407 free(provider);
1408 free(keys);
1409 free(comments);
1410 free_dest_constraints(dest_constraints, ndest_constraints);
1411 send_status(e, success);
1412}
1413
1414static void
1415process_remove_smartcard_key(SocketEntry *e)
1416{
1417 char *provider = NULL((void*)0), *pin = NULL((void*)0), canonical_provider[PATH_MAX1024];
1418 int r, success = 0;
1419 Identity *id, *nxt;
1420
1421 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1421, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1422 if ((r = sshbuf_get_cstring(e->request, &provider, NULL((void*)0))) != 0 ||
1423 (r = sshbuf_get_cstring(e->request, &pin, NULL((void*)0))) != 0) {
1424 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1424, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1425 goto send;
1426 }
1427 free(pin);
1428
1429 if (realpath(provider, canonical_provider) == NULL((void*)0)) {
1430 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1431, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed PKCS#11 add of \"%.100s\": realpath: %s"
, provider, strerror((*__errno())))
1431 provider, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1431, 0, SYSLOG_LEVEL_VERBOSE, ((void*)0), "failed PKCS#11 add of \"%.100s\": realpath: %s"
, provider, strerror((*__errno())))
;
1432 goto send;
1433 }
1434
1435 debug_f("remove %.100s", canonical_provider)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1435, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "remove %.100s", canonical_provider
)
;
1436 for (id = TAILQ_FIRST(&idtab->idlist)((&idtab->idlist)->tqh_first); id; id = nxt) {
1437 nxt = TAILQ_NEXT(id, next)((id)->next.tqe_next);
1438 /* Skip file--based keys */
1439 if (id->provider == NULL((void*)0))
1440 continue;
1441 if (!strcmp(canonical_provider, id->provider)) {
1442 TAILQ_REMOVE(&idtab->idlist, id, next)do { if (((id)->next.tqe_next) != ((void*)0)) (id)->next
.tqe_next->next.tqe_prev = (id)->next.tqe_prev; else (&
idtab->idlist)->tqh_last = (id)->next.tqe_prev; *(id
)->next.tqe_prev = (id)->next.tqe_next; ; ; } while (0)
;
1443 free_identity(id);
1444 idtab->nentries--;
1445 }
1446 }
1447 if (pkcs11_del_provider(canonical_provider) == 0)
1448 success = 1;
1449 else
1450 error_f("pkcs11_del_provider failed")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1450, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "pkcs11_del_provider failed"
)
;
1451send:
1452 free(provider);
1453 send_status(e, success);
1454}
1455#endif /* ENABLE_PKCS11 */
1456
1457static int
1458process_ext_session_bind(SocketEntry *e)
1459{
1460 int r, sid_match, key_match;
1461 struct sshkey *key = NULL((void*)0);
1462 struct sshbuf *sid = NULL((void*)0), *sig = NULL((void*)0);
1463 char *fp = NULL((void*)0);
1464 size_t i;
1465 u_char fwd = 0;
1466
1467 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1467, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1468 if ((r = sshkey_froms(e->request, &key)) != 0 ||
1469 (r = sshbuf_froms(e->request, &sid)) != 0 ||
1470 (r = sshbuf_froms(e->request, &sig)) != 0 ||
1471 (r = sshbuf_get_u8(e->request, &fwd)) != 0) {
1472 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1472, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1473 goto out;
1474 }
1475 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT2,
1476 SSH_FP_DEFAULT)) == NULL((void*)0))
1477 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1477, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
1478 /* check signature with hostkey on session ID */
1479 if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig),
1480 sshbuf_ptr(sid), sshbuf_len(sid), NULL((void*)0), 0, NULL((void*)0))) != 0) {
1481 error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1481, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshkey_verify for %s %s"
, sshkey_type(key), fp)
;
1482 goto out;
1483 }
1484 /* check whether sid/key already recorded */
1485 for (i = 0; i < e->nsession_ids; i++) {
1486 if (!e->session_ids[i].forwarded) {
1487 error_f("attempt to bind session ID to socket "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1488, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "attempt to bind session ID to socket "
"previously bound for authentication attempt")
1488 "previously bound for authentication attempt")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1488, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "attempt to bind session ID to socket "
"previously bound for authentication attempt")
;
1489 r = -1;
1490 goto out;
1491 }
1492 sid_match = buf_equal(sid, e->session_ids[i].sid) == 0;
1493 key_match = sshkey_equal(key, e->session_ids[i].key);
1494 if (sid_match && key_match) {
1495 debug_f("session ID already recorded for %s %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1496, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "session ID already recorded for %s %s"
, sshkey_type(key), fp)
1496 sshkey_type(key), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1496, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "session ID already recorded for %s %s"
, sshkey_type(key), fp)
;
1497 r = 0;
1498 goto out;
1499 } else if (sid_match) {
1500 error_f("session ID recorded against different key "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1501, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "session ID recorded against different key "
"for %s %s", sshkey_type(key), fp)
1501 "for %s %s", sshkey_type(key), fp)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1501, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "session ID recorded against different key "
"for %s %s", sshkey_type(key), fp)
;
1502 r = -1;
1503 goto out;
1504 }
1505 /*
1506 * new sid with previously-seen key can happen, e.g. multiple
1507 * connections to the same host.
1508 */
1509 }
1510 /* record new key/sid */
1511 if (e->nsession_ids >= AGENT_MAX_SESSION_IDS16) {
1512 error_f("too many session IDs recorded")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1512, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "too many session IDs recorded"
)
;
1513 goto out;
1514 }
1515 e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids,
1516 e->nsession_ids + 1, sizeof(*e->session_ids));
1517 i = e->nsession_ids++;
1518 debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i,sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1519, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "recorded %s %s (slot %zu of %d)"
, sshkey_type(key), fp, i, 16)
1519 AGENT_MAX_SESSION_IDS)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1519, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "recorded %s %s (slot %zu of %d)"
, sshkey_type(key), fp, i, 16)
;
1520 e->session_ids[i].key = key;
1521 e->session_ids[i].forwarded = fwd != 0;
1522 key = NULL((void*)0); /* transferred */
1523 /* can't transfer sid; it's refcounted and scoped to request's life */
1524 if ((e->session_ids[i].sid = sshbuf_new()) == NULL((void*)0))
1525 fatal_f("sshbuf_new")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1525, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new")
;
1526 if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0)
1527 fatal_fr(r, "sshbuf_putb session ID")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1527, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putb session ID"
)
;
1528 /* success */
1529 r = 0;
1530 out:
1531 sshkey_free(key);
1532 sshbuf_free(sid);
1533 sshbuf_free(sig);
1534 return r == 0 ? 1 : 0;
1535}
1536
1537static void
1538process_extension(SocketEntry *e)
1539{
1540 int r, success = 0;
1541 char *name;
1542
1543 debug2_f("entering")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1543, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "entering")
;
1544 if ((r = sshbuf_get_cstring(e->request, &name, NULL((void*)0))) != 0) {
1545 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1545, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1546 goto send;
1547 }
1548 if (strcmp(name, "session-bind@openssh.com") == 0)
1549 success = process_ext_session_bind(e);
1550 else
1551 debug_f("unsupported extension \"%s\"", name)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1551, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "unsupported extension \"%s\""
, name)
;
1552 free(name);
1553send:
1554 send_status(e, success);
1555}
1556/*
1557 * dispatch incoming message.
1558 * returns 1 on success, 0 for incomplete messages or -1 on error.
1559 */
1560static int
1561process_message(u_int socknum)
1562{
1563 u_int msg_len;
1564 u_char type;
1565 const u_char *cp;
1566 int r;
1567 SocketEntry *e;
1568
1569 if (socknum >= sockets_alloc)
1570 fatal_f("sock %u >= allocated %u", socknum, sockets_alloc)sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1570, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sock %u >= allocated %u"
, socknum, sockets_alloc)
;
1571 e = &sockets[socknum];
1572
1573 if (sshbuf_len(e->input) < 5)
1574 return 0; /* Incomplete message header. */
1575 cp = sshbuf_ptr(e->input);
1576 msg_len = PEEK_U32(cp)(((u_int32_t)(((const u_char *)(cp))[0]) << 24) | ((u_int32_t
)(((const u_char *)(cp))[1]) << 16) | ((u_int32_t)(((const
u_char *)(cp))[2]) << 8) | (u_int32_t)(((const u_char *
)(cp))[3]))
;
1577 if (msg_len > AGENT_MAX_LEN(256*1024)) {
1578 debug_f("socket %u (fd=%d) message too long %u > %u",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1579, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "socket %u (fd=%d) message too long %u > %u"
, socknum, e->fd, msg_len, (256*1024))
1579 socknum, e->fd, msg_len, AGENT_MAX_LEN)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1579, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "socket %u (fd=%d) message too long %u > %u"
, socknum, e->fd, msg_len, (256*1024))
;
1580 return -1;
1581 }
1582 if (sshbuf_len(e->input) < msg_len + 4)
1583 return 0; /* Incomplete message body. */
1584
1585 /* move the current input to e->request */
1586 sshbuf_reset(e->request);
1587 if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
1588 (r = sshbuf_get_u8(e->request, &type)) != 0) {
1589 if (r == SSH_ERR_MESSAGE_INCOMPLETE-3 ||
1590 r == SSH_ERR_STRING_TOO_LARGE-6) {
1591 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1591, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
1592 return -1;
1593 }
1594 fatal_fr(r, "parse")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1594, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse")
;
1595 }
1596
1597 debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1597, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "socket %u (fd=%d) type %d"
, socknum, e->fd, type)
;
1598
1599 /* check whether agent is locked */
1600 if (locked && type != SSH_AGENTC_UNLOCK23) {
1601 sshbuf_reset(e->request);
1602 switch (type) {
1603 case SSH2_AGENTC_REQUEST_IDENTITIES11:
1604 /* send empty lists */
1605 no_identities(e);
1606 break;
1607 default:
1608 /* send a fail message for all other request types */
1609 send_status(e, 0);
1610 }
1611 return 1;
1612 }
1613
1614 switch (type) {
1615 case SSH_AGENTC_LOCK22:
1616 case SSH_AGENTC_UNLOCK23:
1617 process_lock_agent(e, type == SSH_AGENTC_LOCK22);
1618 break;
1619 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES9:
1620 process_remove_all_identities(e); /* safe for !WITH_SSH1 */
1621 break;
1622 /* ssh2 */
1623 case SSH2_AGENTC_SIGN_REQUEST13:
1624 process_sign_request2(e);
1625 break;
1626 case SSH2_AGENTC_REQUEST_IDENTITIES11:
1627 process_request_identities(e);
1628 break;
1629 case SSH2_AGENTC_ADD_IDENTITY17:
1630 case SSH2_AGENTC_ADD_ID_CONSTRAINED25:
1631 process_add_identity(e);
1632 break;
1633 case SSH2_AGENTC_REMOVE_IDENTITY18:
1634 process_remove_identity(e);
1635 break;
1636 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES19:
1637 process_remove_all_identities(e);
1638 break;
1639#ifdef ENABLE_PKCS111
1640 case SSH_AGENTC_ADD_SMARTCARD_KEY20:
1641 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED26:
1642 process_add_smartcard_key(e);
1643 break;
1644 case SSH_AGENTC_REMOVE_SMARTCARD_KEY21:
1645 process_remove_smartcard_key(e);
1646 break;
1647#endif /* ENABLE_PKCS11 */
1648 case SSH_AGENTC_EXTENSION27:
1649 process_extension(e);
1650 break;
1651 default:
1652 /* Unknown message. Respond with failure. */
1653 error("Unknown message %d", type)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1653, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unknown message %d"
, type)
;
1654 sshbuf_reset(e->request);
1655 send_status(e, 0);
1656 break;
1657 }
1658 return 1;
1659}
1660
1661static void
1662new_socket(sock_type type, int fd)
1663{
1664 u_int i, old_alloc, new_alloc;
1665
1666 debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" :sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1667, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "type = %s", type
== AUTH_CONNECTION ? "CONNECTION" : (type == AUTH_SOCKET ? "SOCKET"
: "UNKNOWN"))
1667 (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1667, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "type = %s", type
== AUTH_CONNECTION ? "CONNECTION" : (type == AUTH_SOCKET ? "SOCKET"
: "UNKNOWN"))
;
1668 set_nonblock(fd);
1669
1670 if (fd > max_fd)
1671 max_fd = fd;
1672
1673 for (i = 0; i < sockets_alloc; i++)
1674 if (sockets[i].type == AUTH_UNUSED) {
1675 sockets[i].fd = fd;
1676 if ((sockets[i].input = sshbuf_new()) == NULL((void*)0) ||
1677 (sockets[i].output = sshbuf_new()) == NULL((void*)0) ||
1678 (sockets[i].request = sshbuf_new()) == NULL((void*)0))
1679 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1679, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
1680 sockets[i].type = type;
1681 return;
1682 }
1683 old_alloc = sockets_alloc;
1684 new_alloc = sockets_alloc + 10;
1685 sockets = xrecallocarray(sockets, old_alloc, new_alloc,
1686 sizeof(sockets[0]));
1687 for (i = old_alloc; i < new_alloc; i++)
1688 sockets[i].type = AUTH_UNUSED;
1689 sockets_alloc = new_alloc;
1690 sockets[old_alloc].fd = fd;
1691 if ((sockets[old_alloc].input = sshbuf_new()) == NULL((void*)0) ||
1692 (sockets[old_alloc].output = sshbuf_new()) == NULL((void*)0) ||
1693 (sockets[old_alloc].request = sshbuf_new()) == NULL((void*)0))
1694 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1694, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
1695 sockets[old_alloc].type = type;
1696}
1697
1698static int
1699handle_socket_read(u_int socknum)
1700{
1701 struct sockaddr_un sunaddr;
1702 socklen_t slen;
1703 uid_t euid;
1704 gid_t egid;
1705 int fd;
1706
1707 slen = sizeof(sunaddr);
1708 fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
1709 if (fd == -1) {
1710 error("accept from AUTH_SOCKET: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1710, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "accept from AUTH_SOCKET: %s"
, strerror((*__errno())))
;
1711 return -1;
1712 }
1713 if (getpeereid(fd, &euid, &egid) == -1) {
1714 error("getpeereid %d failed: %s", fd, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1714, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "getpeereid %d failed: %s"
, fd, strerror((*__errno())))
;
1715 close(fd);
1716 return -1;
1717 }
1718 if ((euid != 0) && (getuid() != euid)) {
1719 error("uid mismatch: peer euid %u != uid %u",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1720, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "uid mismatch: peer euid %u != uid %u"
, (u_int) euid, (u_int) getuid())
1720 (u_int) euid, (u_int) getuid())sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1720, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "uid mismatch: peer euid %u != uid %u"
, (u_int) euid, (u_int) getuid())
;
1721 close(fd);
1722 return -1;
1723 }
1724 new_socket(AUTH_CONNECTION, fd);
1725 return 0;
1726}
1727
1728static int
1729handle_conn_read(u_int socknum)
1730{
1731 char buf[AGENT_RBUF_LEN(4096)];
1732 ssize_t len;
1733 int r;
1734
1735 if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
1736 if (len == -1) {
1737 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
1738 return 0;
1739 error_f("read error on socket %u (fd %d): %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1740, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "read error on socket %u (fd %d): %s"
, socknum, sockets[socknum].fd, strerror((*__errno())))
1740 socknum, sockets[socknum].fd, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1740, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "read error on socket %u (fd %d): %s"
, socknum, sockets[socknum].fd, strerror((*__errno())))
;
1741 }
1742 return -1;
1743 }
1744 if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
1745 fatal_fr(r, "compose")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1745, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose")
;
1746 explicit_bzero(buf, sizeof(buf));
1747 for (;;) {
1748 if ((r = process_message(socknum)) == -1)
1749 return -1;
1750 else if (r == 0)
1751 break;
1752 }
1753 return 0;
1754}
1755
1756static int
1757handle_conn_write(u_int socknum)
1758{
1759 ssize_t len;
1760 int r;
1761
1762 if (sshbuf_len(sockets[socknum].output) == 0)
1763 return 0; /* shouldn't happen */
1764 if ((len = write(sockets[socknum].fd,
1765 sshbuf_ptr(sockets[socknum].output),
1766 sshbuf_len(sockets[socknum].output))) <= 0) {
1767 if (len == -1) {
1768 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
1769 return 0;
1770 error_f("read error on socket %u (fd %d): %s",sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1771, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "read error on socket %u (fd %d): %s"
, socknum, sockets[socknum].fd, strerror((*__errno())))
1771 socknum, sockets[socknum].fd, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1771, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "read error on socket %u (fd %d): %s"
, socknum, sockets[socknum].fd, strerror((*__errno())))
;
1772 }
1773 return -1;
1774 }
1775 if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
1776 fatal_fr(r, "consume")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1776, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "consume")
;
1777 return 0;
1778}
1779
1780static void
1781after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
1782{
1783 size_t i;
1784 u_int socknum, activefds = npfd;
1785
1786 for (i = 0; i < npfd; i++) {
1787 if (pfd[i].revents == 0)
1788 continue;
1789 /* Find sockets entry */
1790 for (socknum = 0; socknum < sockets_alloc; socknum++) {
1791 if (sockets[socknum].type != AUTH_SOCKET &&
1792 sockets[socknum].type != AUTH_CONNECTION)
1793 continue;
1794 if (pfd[i].fd == sockets[socknum].fd)
1795 break;
1796 }
1797 if (socknum >= sockets_alloc) {
1798 error_f("no socket for fd %d", pfd[i].fd)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1798, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "no socket for fd %d"
, pfd[i].fd)
;
1799 continue;
1800 }
1801 /* Process events */
1802 switch (sockets[socknum].type) {
1803 case AUTH_SOCKET:
1804 if ((pfd[i].revents & (POLLIN0x0001|POLLERR0x0008)) == 0)
1805 break;
1806 if (npfd > maxfds) {
1807 debug3("out of fds (active %u >= limit %u); "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1808, 0, SYSLOG_LEVEL_DEBUG3, ((void*)0), "out of fds (active %u >= limit %u); "
"skipping accept", activefds, maxfds)
1808 "skipping accept", activefds, maxfds)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1808, 0, SYSLOG_LEVEL_DEBUG3, ((void*)0), "out of fds (active %u >= limit %u); "
"skipping accept", activefds, maxfds)
;
1809 break;
1810 }
1811 if (handle_socket_read(socknum) == 0)
1812 activefds++;
1813 break;
1814 case AUTH_CONNECTION:
1815 if ((pfd[i].revents & (POLLIN0x0001|POLLHUP0x0010|POLLERR0x0008)) != 0 &&
1816 handle_conn_read(socknum) != 0)
1817 goto close_sock;
1818 if ((pfd[i].revents & (POLLOUT0x0004|POLLHUP0x0010)) != 0 &&
1819 handle_conn_write(socknum) != 0) {
1820 close_sock:
1821 if (activefds == 0)
1822 fatal("activefds == 0 at close_sock")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1822, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "activefds == 0 at close_sock"
)
;
1823 close_socket(&sockets[socknum]);
1824 activefds--;
1825 break;
1826 }
1827 break;
1828 default:
1829 break;
1830 }
1831 }
1832}
1833
1834static int
1835prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
1836{
1837 struct pollfd *pfd = *pfdp;
1838 size_t i, j, npfd = 0;
1839 time_t deadline;
1840 int r;
1841
1842 /* Count active sockets */
1843 for (i = 0; i < sockets_alloc; i++) {
1844 switch (sockets[i].type) {
1845 case AUTH_SOCKET:
1846 case AUTH_CONNECTION:
1847 npfd++;
1848 break;
1849 case AUTH_UNUSED:
1850 break;
1851 default:
1852 fatal("Unknown socket type %d", sockets[i].type)sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1852, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Unknown socket type %d"
, sockets[i].type)
;
1853 break;
1854 }
1855 }
1856 if (npfd != *npfdp &&
1857 (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL((void*)0))
1858 fatal_f("recallocarray failed")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1858, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "recallocarray failed"
)
;
1859 *pfdp = pfd;
1860 *npfdp = npfd;
1861
1862 for (i = j = 0; i < sockets_alloc; i++) {
1863 switch (sockets[i].type) {
1864 case AUTH_SOCKET:
1865 if (npfd > maxfds) {
1866 debug3("out of fds (active %zu >= limit %u); "sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1867, 0, SYSLOG_LEVEL_DEBUG3, ((void*)0), "out of fds (active %zu >= limit %u); "
"skipping arming listener", npfd, maxfds)
1867 "skipping arming listener", npfd, maxfds)sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1867, 0, SYSLOG_LEVEL_DEBUG3, ((void*)0), "out of fds (active %zu >= limit %u); "
"skipping arming listener", npfd, maxfds)
;
1868 break;
1869 }
1870 pfd[j].fd = sockets[i].fd;
1871 pfd[j].revents = 0;
1872 pfd[j].events = POLLIN0x0001;
1873 j++;
1874 break;
1875 case AUTH_CONNECTION:
1876 pfd[j].fd = sockets[i].fd;
1877 pfd[j].revents = 0;
1878 /*
1879 * Only prepare to read if we can handle a full-size
1880 * input read buffer and enqueue a max size reply..
1881 */
1882 if ((r = sshbuf_check_reserve(sockets[i].input,
1883 AGENT_RBUF_LEN(4096))) == 0 &&
1884 (r = sshbuf_check_reserve(sockets[i].output,
1885 AGENT_MAX_LEN(256*1024))) == 0)
1886 pfd[j].events = POLLIN0x0001;
1887 else if (r != SSH_ERR_NO_BUFFER_SPACE-9)
1888 fatal_fr(r, "reserve")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1888, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "reserve")
;
1889 if (sshbuf_len(sockets[i].output) > 0)
1890 pfd[j].events |= POLLOUT0x0004;
1891 j++;
1892 break;
1893 default:
1894 break;
1895 }
1896 }
1897 deadline = reaper();
1898 if (parent_alive_interval != 0)
1899 deadline = (deadline == 0) ? parent_alive_interval :
1900 MINIMUM(deadline, parent_alive_interval)(((deadline) < (parent_alive_interval)) ? (deadline) : (parent_alive_interval
))
;
1901 if (deadline == 0) {
1902 *timeoutp = -1; /* INFTIM */
1903 } else {
1904 if (deadline > INT_MAX2147483647 / 1000)
1905 *timeoutp = INT_MAX2147483647 / 1000;
1906 else
1907 *timeoutp = deadline * 1000;
1908 }
1909 return (1);
1910}
1911
1912static void
1913cleanup_socket(void)
1914{
1915 if (cleanup_pid != 0 && getpid() != cleanup_pid)
1916 return;
1917 debug_f("cleanup")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1917, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "cleanup")
;
1918 if (socket_name[0])
1919 unlink(socket_name);
1920 if (socket_dir[0])
1921 rmdir(socket_dir);
1922}
1923
1924void
1925cleanup_exit(int i)
1926{
1927 cleanup_socket();
1928 _exit(i);
1929}
1930
1931/*ARGSUSED*/
1932static void
1933cleanup_handler(int sig)
1934{
1935 cleanup_socket();
1936#ifdef ENABLE_PKCS111
1937 pkcs11_terminate();
1938#endif
1939 _exit(2);
1940}
1941
1942static void
1943check_parent_exists(void)
1944{
1945 /*
1946 * If our parent has exited then getppid() will return (pid_t)1,
1947 * so testing for that should be safe.
1948 */
1949 if (parent_pid != -1 && getppid() != parent_pid) {
1950 /* printf("Parent has died - Authentication agent exiting.\n"); */
1951 cleanup_socket();
1952 _exit(2);
1953 }
1954}
1955
1956static void
1957usage(void)
1958{
1959 fprintf(stderr(&__sF[2]),
1960 "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
1961 " [-P allowed_providers] [-t life]\n"
1962 " ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers]\n"
1963 " [-t life] command [arg ...]\n"
1964 " ssh-agent [-c | -s] -k\n");
1965 exit(1);
1966}
1967
1968int
1969main(int ac, char **av)
1970{
1971 int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
1972 int sock, ch, result, saved_errno;
1973 char *shell, *format, *pidstr, *agentsocket = NULL((void*)0);
1974 struct rlimit rlim;
1975 extern int optind;
1976 extern char *optarg;
1977 pid_t pid;
1978 char pidstrbuf[1 + 3 * sizeof pid];
1979 size_t len;
1980 mode_t prev_mask;
1981 int timeout = -1; /* INFTIM */
1982 struct pollfd *pfd = NULL((void*)0);
1983 size_t npfd = 0;
1984 u_int maxfds;
1985
1986 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1987 sanitise_stdfd();
1988
1989 /* drop */
1990 setegid(getgid());
1991 setgid(getgid());
The return value from the call to 'setgid' is not checked. If an error occurs in 'setgid', the following code may execute with unexpected privileges
1992
1993 if (getrlimit(RLIMIT_NOFILE8, &rlim) == -1)
1994 fatal("%s: getrlimit: %s", __progname, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 1994, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: getrlimit: %s"
, __progname, strerror((*__errno())))
;
1995
1996#ifdef WITH_OPENSSL1
1997 OpenSSL_add_all_algorithms()OPENSSL_add_all_algorithms_noconf();
1998#endif
1999
2000 while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
2001 switch (ch) {
2002 case 'E':
2003 fingerprint_hash = ssh_digest_alg_by_name(optarg);
2004 if (fingerprint_hash == -1)
2005 fatal("Invalid hash algorithm \"%s\"", optarg)sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2005, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid hash algorithm \"%s\""
, optarg)
;
2006 break;
2007 case 'c':
2008 if (s_flag)
2009 usage();
2010 c_flag++;
2011 break;
2012 case 'k':
2013 k_flag++;
2014 break;
2015 case 'O':
2016 if (strcmp(optarg, "no-restrict-websafe") == 0)
2017 restrict_websafe = 0;
2018 else
2019 fatal("Unknown -O option")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2019, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Unknown -O option"
)
;
2020 break;
2021 case 'P':
2022 if (allowed_providers != NULL((void*)0))
2023 fatal("-P option already specified")sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2023, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "-P option already specified"
)
;
2024 allowed_providers = xstrdup(optarg);
2025 break;
2026 case 's':
2027 if (c_flag)
2028 usage();
2029 s_flag++;
2030 break;
2031 case 'd':
2032 if (d_flag || D_flag)
2033 usage();
2034 d_flag++;
2035 break;
2036 case 'D':
2037 if (d_flag || D_flag)
2038 usage();
2039 D_flag++;
2040 break;
2041 case 'a':
2042 agentsocket = optarg;
2043 break;
2044 case 't':
2045 if ((lifetime = convtime(optarg)) == -1) {
2046 fprintf(stderr(&__sF[2]), "Invalid lifetime\n");
2047 usage();
2048 }
2049 break;
2050 default:
2051 usage();
2052 }
2053 }
2054 ac -= optind;
2055 av += optind;
2056
2057 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
2058 usage();
2059
2060 if (allowed_providers == NULL((void*)0))
2061 allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS"/usr/lib*/*,/usr/local/lib*/*");
2062
2063 if (ac == 0 && !c_flag && !s_flag) {
2064 shell = getenv("SHELL");
2065 if (shell != NULL((void*)0) && (len = strlen(shell)) > 2 &&
2066 strncmp(shell + len - 3, "csh", 3) == 0)
2067 c_flag = 1;
2068 }
2069 if (k_flag) {
2070 const char *errstr = NULL((void*)0);
2071
2072 pidstr = getenv(SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID");
2073 if (pidstr == NULL((void*)0)) {
2074 fprintf(stderr(&__sF[2]), "%s not set, cannot kill agent\n",
2075 SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID");
2076 exit(1);
2077 }
2078 pid = (int)strtonum(pidstr, 2, INT_MAX2147483647, &errstr);
2079 if (errstr) {
2080 fprintf(stderr(&__sF[2]),
2081 "%s=\"%s\", which is not a good PID: %s\n",
2082 SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID", pidstr, errstr);
2083 exit(1);
2084 }
2085 if (kill(pid, SIGTERM15) == -1) {
2086 perror("kill");
2087 exit(1);
2088 }
2089 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
2090 printf(format, SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK");
2091 printf(format, SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID");
2092 printf("echo Agent pid %ld killed;\n", (long)pid);
2093 exit(0);
2094 }
2095
2096 /*
2097 * Minimum file descriptors:
2098 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2099 * a few spare for libc / stack protectors / sanitisers, etc.
2100 */
2101#define SSH_AGENT_MIN_FDS(3+1+1+1+4) (3+1+1+1+4)
2102 if (rlim.rlim_cur < SSH_AGENT_MIN_FDS(3+1+1+1+4))
2103 fatal("%s: file descriptor rlimit %lld too low (minimum %u)",sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2104, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: file descriptor rlimit %lld too low (minimum %u)"
, __progname, (long long)rlim.rlim_cur, (3+1+1+1+4))
2104 __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS)sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2104, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: file descriptor rlimit %lld too low (minimum %u)"
, __progname, (long long)rlim.rlim_cur, (3+1+1+1+4))
;
2105 maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS(3+1+1+1+4);
2106
2107 parent_pid = getpid();
2108
2109 if (agentsocket == NULL((void*)0)) {
2110 /* Create private directory for agent socket */
2111 mktemp_proto(socket_dir, sizeof(socket_dir));
2112 if (mkdtemp(socket_dir) == NULL((void*)0)) {
2113 perror("mkdtemp: private socket dir");
2114 exit(1);
2115 }
2116 snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
2117 (long)parent_pid);
2118 } else {
2119 /* Try to use specified agent socket */
2120 socket_dir[0] = '\0';
2121 strlcpy(socket_name, agentsocket, sizeof socket_name);
2122 }
2123
2124 /*
2125 * Create socket early so it will exist before command gets run from
2126 * the parent.
2127 */
2128 prev_mask = umask(0177);
2129 sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG128, 0);
2130 if (sock < 0) {
2131 /* XXX - unix_listener() calls error() not perror() */
2132 *socket_name = '\0'; /* Don't unlink any existing file */
2133 cleanup_exit(1);
2134 }
2135 umask(prev_mask);
2136
2137 /*
2138 * Fork, and have the parent execute the command, if any, or present
2139 * the socket data. The child continues as the authentication agent.
2140 */
2141 if (D_flag || d_flag) {
2142 log_init(__progname,
2143 d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
2144 SYSLOG_FACILITY_AUTH, 1);
2145 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2146 printf(format, SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK", socket_name,
2147 SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK");
2148 printf("echo Agent pid %ld;\n", (long)parent_pid);
2149 fflush(stdout(&__sF[1]));
2150 goto skip;
2151 }
2152 pid = fork();
2153 if (pid == -1) {
2154 perror("fork");
2155 cleanup_exit(1);
2156 }
2157 if (pid != 0) { /* Parent - execute the given command. */
2158 close(sock);
2159 snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
2160 if (ac == 0) {
2161 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2162 printf(format, SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK", socket_name,
2163 SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK");
2164 printf(format, SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID", pidstrbuf,
2165 SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID");
2166 printf("echo Agent pid %ld;\n", (long)pid);
2167 exit(0);
2168 }
2169 if (setenv(SSH_AUTHSOCKET_ENV_NAME"SSH_AUTH_SOCK", socket_name, 1) == -1 ||
2170 setenv(SSH_AGENTPID_ENV_NAME"SSH_AGENT_PID", pidstrbuf, 1) == -1) {
2171 perror("setenv");
2172 exit(1);
2173 }
2174 execvp(av[0], av);
2175 perror(av[0]);
2176 exit(1);
2177 }
2178 /* child */
2179 log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
2180
2181 if (setsid() == -1) {
2182 error("setsid: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2182, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "setsid: %s", strerror
((*__errno())))
;
2183 cleanup_exit(1);
2184 }
2185
2186 (void)chdir("/");
2187 if (stdfd_devnull(1, 1, 1) == -1)
2188 error_f("stdfd_devnull failed")sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2188, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "stdfd_devnull failed"
)
;
2189
2190 /* deny core dumps, since memory contains unencrypted private keys */
2191 rlim.rlim_cur = rlim.rlim_max = 0;
2192 if (setrlimit(RLIMIT_CORE4, &rlim) == -1) {
2193 error("setrlimit RLIMIT_CORE: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2193, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "setrlimit RLIMIT_CORE: %s"
, strerror((*__errno())))
;
2194 cleanup_exit(1);
2195 }
2196
2197skip:
2198
2199 cleanup_pid = getpid();
2200
2201#ifdef ENABLE_PKCS111
2202 pkcs11_init(0);
2203#endif
2204 new_socket(AUTH_SOCKET, sock);
2205 if (ac > 0)
2206 parent_alive_interval = 10;
2207 idtab_init();
2208 ssh_signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
2209 ssh_signal(SIGINT2, (d_flag | D_flag) ? cleanup_handler : SIG_IGN(void (*)(int))1);
2210 ssh_signal(SIGHUP1, cleanup_handler);
2211 ssh_signal(SIGTERM15, cleanup_handler);
2212
2213 if (pledge("stdio rpath cpath unix id proc exec", NULL((void*)0)) == -1)
2214 fatal("%s: pledge: %s", __progname, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2214, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: pledge: %s", __progname
, strerror((*__errno())))
;
2215
2216 while (1) {
2217 prepare_poll(&pfd, &npfd, &timeout, maxfds);
2218 result = poll(pfd, npfd, timeout);
2219 saved_errno = errno(*__errno());
2220 if (parent_alive_interval != 0)
2221 check_parent_exists();
2222 (void) reaper(); /* remove expired keys */
2223 if (result == -1) {
2224 if (saved_errno == EINTR4)
2225 continue;
2226 fatal("poll: %s", strerror(saved_errno))sshfatal("/usr/src/usr.bin/ssh/ssh-agent/../ssh-agent.c", __func__
, 2226, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "poll: %s", strerror
(saved_errno))
;
2227 } else if (result > 0)
2228 after_poll(pfd, npfd, maxfds);
2229 }
2230 /* NOTREACHED */
2231}