1 /* $OpenBSD: ssh-agent.c,v 1.330 2026/07/05 02:46:44 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 "includes.h" 38 39 #include <sys/types.h> 40 #include <sys/time.h> 41 #include <sys/queue.h> 42 #include <sys/resource.h> 43 #include <sys/socket.h> 44 #include <sys/stat.h> 45 #include <sys/un.h> 46 #include <sys/wait.h> 47 48 #ifdef WITH_OPENSSL 49 #include <openssl/evp.h> 50 #include "openbsd-compat/openssl-compat.h" 51 #endif 52 53 #include <errno.h> 54 #include <fcntl.h> 55 #include <paths.h> 56 #include <poll.h> 57 #include <signal.h> 58 #include <stdlib.h> 59 #include <stdio.h> 60 #include <string.h> 61 #include <stdarg.h> 62 #include <limits.h> 63 #include <time.h> 64 #include <unistd.h> 65 #include <util.h> 66 67 #include "xmalloc.h" 68 #include "ssh.h" 69 #include "ssh2.h" 70 #include "sshbuf.h" 71 #include "sshkey.h" 72 #include "authfd.h" 73 #include "log.h" 74 #include "misc.h" 75 #include "digest.h" 76 #include "ssherr.h" 77 #include "match.h" 78 #include "msg.h" 79 #include "pathnames.h" 80 #include "ssh-pkcs11.h" 81 #include "sk-api.h" 82 #include "myproposal.h" 83 #include "version.h" 84 85 #ifndef DEFAULT_ALLOWED_PROVIDERS 86 # define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*" 87 #endif 88 #ifndef DEFAULT_WEBSAFE_ALLOWLIST 89 # define DEFAULT_WEBSAFE_ALLOWLIST "ssh:*" 90 #endif 91 92 /* Maximum accepted message length */ 93 #define AGENT_MAX_LEN (256*1024) 94 /* Maximum bytes to read from client socket */ 95 #define AGENT_RBUF_LEN (4096) 96 /* Maximum number of recorded session IDs/hostkeys per connection */ 97 #define AGENT_MAX_SESSION_IDS 16 98 /* Maximum size of session ID */ 99 #define AGENT_MAX_SID_LEN 128 100 /* Maximum number of destination constraints to accept on a key */ 101 #define AGENT_MAX_DEST_CONSTRAINTS 1024 102 /* Maximum number of associated certificate constraints to accept on a key */ 103 #define AGENT_MAX_EXT_CERTS 1024 104 /* Max length of username constraint */ 105 #define AGENT_USER_CONSTRAINT_MAX_LEN 256 106 107 /* XXX store hostkey_sid in a refcounted tree */ 108 109 typedef enum { 110 AUTH_UNUSED = 0, 111 AUTH_SOCKET = 1, 112 AUTH_CONNECTION = 2, 113 } sock_type; 114 115 struct hostkey_sid { 116 struct sshkey *key; 117 struct sshbuf *sid; 118 int forwarded; 119 }; 120 121 typedef struct socket_entry { 122 int fd; 123 sock_type type; 124 struct sshbuf *input; 125 struct sshbuf *output; 126 struct sshbuf *request; 127 size_t nsession_ids; 128 struct hostkey_sid *session_ids; 129 int session_bind_attempted; 130 } SocketEntry; 131 132 u_int sockets_alloc = 0; 133 SocketEntry *sockets = NULL; 134 135 typedef struct identity { 136 TAILQ_ENTRY(identity) next; 137 struct sshkey *key; 138 char *comment; 139 char *provider; 140 time_t death; 141 u_int confirm; 142 char *sk_provider; 143 struct dest_constraint *dest_constraints; 144 size_t ndest_constraints; 145 } Identity; 146 147 struct idtable { 148 int nentries; 149 TAILQ_HEAD(idqueue, identity) idlist; 150 }; 151 152 /* private key table */ 153 struct idtable *idtab; 154 155 int max_fd = 0; 156 157 /* pid of shell == parent of agent */ 158 pid_t parent_pid = -1; 159 time_t parent_alive_interval = 0; 160 161 static sig_atomic_t signalled_exit; 162 static sig_atomic_t signalled_keydrop; 163 164 /* pid of process for which cleanup_socket is applicable */ 165 pid_t cleanup_pid = 0; 166 167 /* pathname and directory for AUTH_SOCKET */ 168 static char *socket_name; 169 static char socket_dir[PATH_MAX]; 170 171 /* Pattern-list of allowed PKCS#11/Security key paths */ 172 static char *allowed_providers; 173 174 /* 175 * Allows PKCS11 providers or SK keys that use non-internal providers to 176 * be added over a remote connection (identified by session-bind@openssh.com). 177 */ 178 static int remote_add_provider; 179 180 /* locking */ 181 #define LOCK_SIZE 32 182 #define LOCK_SALT_SIZE 16 183 #define LOCK_ROUNDS 1 184 int locked = 0; 185 u_char lock_pwhash[LOCK_SIZE]; 186 u_char lock_salt[LOCK_SALT_SIZE]; 187 188 extern char *__progname; 189 190 /* Default lifetime in seconds (0 == forever) */ 191 static int lifetime = 0; 192 193 static int fingerprint_hash = SSH_FP_HASH_DEFAULT; 194 195 /* Refuse signing of non-SSH messages for web-origin FIDO keys */ 196 static int restrict_websafe = 1; 197 static char *websafe_allowlist; 198 199 /* 200 * Client connection count; incremented in new_socket() and decremented in 201 * close_socket(). When it reaches 0, ssh-agent will exit. Since it is 202 * normally initialized to 1, it will never reach 0. However, if the -x 203 * option is specified, it is initialized to 0 in main(); in that case, 204 * ssh-agent will exit as soon as it has had at least one client but no 205 * longer has any. 206 */ 207 static int xcount = 1; 208 209 static void 210 close_socket(SocketEntry *e) 211 { 212 size_t i; 213 int last = 0; 214 215 if (e->type == AUTH_CONNECTION) { 216 debug("xcount %d -> %d", xcount, xcount - 1); 217 if (--xcount == 0) 218 last = 1; 219 } 220 close(e->fd); 221 sshbuf_free(e->input); 222 sshbuf_free(e->output); 223 sshbuf_free(e->request); 224 for (i = 0; i < e->nsession_ids; i++) { 225 sshkey_free(e->session_ids[i].key); 226 sshbuf_free(e->session_ids[i].sid); 227 } 228 free(e->session_ids); 229 memset(e, '\0', sizeof(*e)); 230 e->fd = -1; 231 e->type = AUTH_UNUSED; 232 if (last) 233 cleanup_exit(0); 234 } 235 236 static void 237 idtab_init(void) 238 { 239 idtab = xcalloc(1, sizeof(*idtab)); 240 TAILQ_INIT(&idtab->idlist); 241 idtab->nentries = 0; 242 } 243 244 static void 245 free_dest_constraint_hop(struct dest_constraint_hop *dch) 246 { 247 u_int i; 248 249 if (dch == NULL) 250 return; 251 free(dch->user); 252 free(dch->hostname); 253 for (i = 0; i < dch->nkeys; i++) 254 sshkey_free(dch->keys[i]); 255 free(dch->keys); 256 free(dch->key_is_ca); 257 } 258 259 static void 260 free_dest_constraints(struct dest_constraint *dcs, size_t ndcs) 261 { 262 size_t i; 263 264 for (i = 0; i < ndcs; i++) { 265 free_dest_constraint_hop(&dcs[i].from); 266 free_dest_constraint_hop(&dcs[i].to); 267 } 268 free(dcs); 269 } 270 271 #ifdef ENABLE_PKCS11 272 static void 273 dup_dest_constraint_hop(const struct dest_constraint_hop *dch, 274 struct dest_constraint_hop *out) 275 { 276 u_int i; 277 int r; 278 279 out->user = dch->user == NULL ? NULL : xstrdup(dch->user); 280 out->hostname = dch->hostname == NULL ? NULL : xstrdup(dch->hostname); 281 out->is_ca = dch->is_ca; 282 out->nkeys = dch->nkeys; 283 out->keys = out->nkeys == 0 ? NULL : 284 xcalloc(out->nkeys, sizeof(*out->keys)); 285 out->key_is_ca = out->nkeys == 0 ? NULL : 286 xcalloc(out->nkeys, sizeof(*out->key_is_ca)); 287 for (i = 0; i < dch->nkeys; i++) { 288 if (dch->keys[i] != NULL && 289 (r = sshkey_from_private(dch->keys[i], 290 &(out->keys[i]))) != 0) 291 fatal_fr(r, "copy key"); 292 out->key_is_ca[i] = dch->key_is_ca[i]; 293 } 294 } 295 296 static struct dest_constraint * 297 dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs) 298 { 299 size_t i; 300 struct dest_constraint *ret; 301 302 if (ndcs == 0) 303 return NULL; 304 ret = xcalloc(ndcs, sizeof(*ret)); 305 for (i = 0; i < ndcs; i++) { 306 dup_dest_constraint_hop(&dcs[i].from, &ret[i].from); 307 dup_dest_constraint_hop(&dcs[i].to, &ret[i].to); 308 } 309 return ret; 310 } 311 #endif /* ENABLE_PKCS11 */ 312 313 #ifdef DEBUG_CONSTRAINTS 314 static void 315 dump_dest_constraint_hop(const struct dest_constraint_hop *dch) 316 { 317 u_int i; 318 char *fp; 319 320 debug_f("user %s hostname %s is_ca %d nkeys %u", 321 dch->user == NULL ? "(null)" : dch->user, 322 dch->hostname == NULL ? "(null)" : dch->hostname, 323 dch->is_ca, dch->nkeys); 324 for (i = 0; i < dch->nkeys; i++) { 325 fp = NULL; 326 if (dch->keys[i] != NULL && 327 (fp = sshkey_fingerprint(dch->keys[i], 328 SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) 329 fatal_f("fingerprint failed"); 330 debug_f("key %u/%u: %s%s%s key_is_ca %d", i, dch->nkeys, 331 dch->keys[i] == NULL ? "" : sshkey_ssh_name(dch->keys[i]), 332 dch->keys[i] == NULL ? "" : " ", 333 dch->keys[i] == NULL ? "none" : fp, 334 dch->key_is_ca[i]); 335 free(fp); 336 } 337 } 338 #endif /* DEBUG_CONSTRAINTS */ 339 340 static void 341 dump_dest_constraints(const char *context, 342 const struct dest_constraint *dcs, size_t ndcs) 343 { 344 #ifdef DEBUG_CONSTRAINTS 345 size_t i; 346 347 debug_f("%s: %zu constraints", context, ndcs); 348 for (i = 0; i < ndcs; i++) { 349 debug_f("constraint %zu / %zu: from: ", i, ndcs); 350 dump_dest_constraint_hop(&dcs[i].from); 351 debug_f("constraint %zu / %zu: to: ", i, ndcs); 352 dump_dest_constraint_hop(&dcs[i].to); 353 } 354 debug_f("done for %s", context); 355 #endif /* DEBUG_CONSTRAINTS */ 356 } 357 358 static void 359 free_identity(Identity *id) 360 { 361 sshkey_free(id->key); 362 free(id->provider); 363 free(id->comment); 364 free(id->sk_provider); 365 free_dest_constraints(id->dest_constraints, id->ndest_constraints); 366 free(id); 367 } 368 369 /* 370 * Match 'key' against the key/CA list in a destination constraint hop 371 * Returns 0 on success or -1 otherwise. 372 */ 373 static int 374 match_key_hop(const char *tag, const struct sshkey *key, 375 const struct dest_constraint_hop *dch) 376 { 377 const char *reason = NULL; 378 const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)"; 379 u_int i; 380 char *fp; 381 382 if (key == NULL) 383 return -1; 384 /* XXX logspam */ 385 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, 386 SSH_FP_DEFAULT)) == NULL) 387 fatal_f("fingerprint failed"); 388 debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail", 389 tag, hostname, sshkey_type(key), fp, dch->nkeys); 390 free(fp); 391 for (i = 0; i < dch->nkeys; i++) { 392 if (dch->keys[i] == NULL) 393 return -1; 394 /* XXX logspam */ 395 if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT, 396 SSH_FP_DEFAULT)) == NULL) 397 fatal_f("fingerprint failed"); 398 debug3_f("%s: key %u: %s%s %s", tag, i, 399 dch->key_is_ca[i] ? "CA " : "", 400 sshkey_type(dch->keys[i]), fp); 401 free(fp); 402 if (!sshkey_is_cert(key)) { 403 /* plain key */ 404 if (dch->key_is_ca[i] || 405 !sshkey_equal(key, dch->keys[i])) 406 continue; 407 return 0; 408 } 409 /* certificate */ 410 if (!dch->key_is_ca[i]) 411 continue; 412 if (key->cert == NULL || key->cert->signature_key == NULL) 413 return -1; /* shouldn't happen */ 414 if (!sshkey_equal(key->cert->signature_key, dch->keys[i])) 415 continue; 416 if (sshkey_cert_check_host(key, hostname, 417 SSH_ALLOWED_CA_SIGALGS, &reason) != 0) { 418 debug_f("cert %s / hostname %s rejected: %s", 419 key->cert->key_id, hostname, reason); 420 continue; 421 } 422 return 0; 423 } 424 return -1; 425 } 426 427 /* Check destination constraints on an identity against the hostkey/user */ 428 static int 429 permitted_by_dest_constraints(const struct sshkey *fromkey, 430 const struct sshkey *tokey, Identity *id, const char *user, 431 const char **hostnamep) 432 { 433 size_t i; 434 struct dest_constraint *d; 435 436 if (hostnamep != NULL) 437 *hostnamep = NULL; 438 for (i = 0; i < id->ndest_constraints; i++) { 439 d = id->dest_constraints + i; 440 /* XXX remove logspam */ 441 debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)", 442 i, d->from.user ? d->from.user : "", 443 d->from.user ? "@" : "", 444 d->from.hostname ? d->from.hostname : "(ORIGIN)", 445 d->from.nkeys, 446 d->to.user ? d->to.user : "", d->to.user ? "@" : "", 447 d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys); 448 449 /* Match 'from' key */ 450 if (fromkey == NULL) { 451 /* We are matching the first hop */ 452 if (d->from.hostname != NULL || d->from.nkeys != 0) 453 continue; 454 } else if (match_key_hop("from", fromkey, &d->from) != 0) 455 continue; 456 457 /* Match 'to' key */ 458 if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0) 459 continue; 460 461 /* Match user if specified */ 462 if (d->to.user != NULL && user != NULL && 463 !match_pattern(user, d->to.user)) 464 continue; 465 466 /* successfully matched this constraint */ 467 if (hostnamep != NULL) 468 *hostnamep = d->to.hostname; 469 debug2_f("allowed for hostname %s", 470 d->to.hostname == NULL ? "*" : d->to.hostname); 471 return 0; 472 } 473 /* no match */ 474 debug2_f("%s identity \"%s\" not permitted for this destination", 475 sshkey_type(id->key), id->comment); 476 return -1; 477 } 478 479 /* 480 * Check whether hostkeys on a SocketEntry and the optionally specified user 481 * are permitted by the destination constraints on the Identity. 482 * Returns 0 on success or -1 otherwise. 483 */ 484 static int 485 identity_permitted(Identity *id, SocketEntry *e, char *user, 486 const char **forward_hostnamep, const char **last_hostnamep) 487 { 488 size_t i; 489 const char **hp; 490 struct hostkey_sid *hks; 491 const struct sshkey *fromkey = NULL; 492 const char *test_user; 493 char *fp1, *fp2; 494 495 /* XXX remove logspam */ 496 debug3_f("entering: key %s comment \"%s\", %zu socket bindings, " 497 "%zu constraints", sshkey_type(id->key), id->comment, 498 e->nsession_ids, id->ndest_constraints); 499 if (id->ndest_constraints == 0) 500 return 0; /* unconstrained */ 501 if (e->session_bind_attempted && e->nsession_ids == 0) { 502 error_f("previous session bind failed on socket"); 503 return -1; 504 } 505 if (e->nsession_ids == 0) 506 return 0; /* local use */ 507 /* 508 * Walk through the hops recorded by session_id and try to find a 509 * constraint that satisfies each. 510 */ 511 for (i = 0; i < e->nsession_ids; i++) { 512 hks = e->session_ids + i; 513 if (hks->key == NULL) 514 fatal_f("internal error: no bound key"); 515 /* XXX remove logspam */ 516 fp1 = fp2 = NULL; 517 if (fromkey != NULL && 518 (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT, 519 SSH_FP_DEFAULT)) == NULL) 520 fatal_f("fingerprint failed"); 521 if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT, 522 SSH_FP_DEFAULT)) == NULL) 523 fatal_f("fingerprint failed"); 524 debug3_f("socketentry fd=%d, entry %zu %s, " 525 "from hostkey %s %s to user %s hostkey %s %s", 526 e->fd, i, hks->forwarded ? "FORWARD" : "AUTH", 527 fromkey ? sshkey_type(fromkey) : "(ORIGIN)", 528 fromkey ? fp1 : "", user ? user : "(ANY)", 529 sshkey_type(hks->key), fp2); 530 free(fp1); 531 free(fp2); 532 /* 533 * Record the hostnames for the initial forwarding and 534 * the final destination. 535 */ 536 hp = NULL; 537 if (i == e->nsession_ids - 1) 538 hp = last_hostnamep; 539 else if (i == 0) 540 hp = forward_hostnamep; 541 /* Special handling for final recorded binding */ 542 test_user = NULL; 543 if (i == e->nsession_ids - 1) { 544 /* Can only check user at final hop */ 545 test_user = user; 546 /* 547 * user is only presented for signature requests. 548 * If this is the case, make sure last binding is not 549 * for a forwarding. 550 */ 551 if (hks->forwarded && user != NULL) { 552 error_f("tried to sign on forwarding hop"); 553 return -1; 554 } 555 } else if (!hks->forwarded) { 556 error_f("tried to forward though signing bind"); 557 return -1; 558 } 559 if (permitted_by_dest_constraints(fromkey, hks->key, id, 560 test_user, hp) != 0) 561 return -1; 562 fromkey = hks->key; 563 } 564 /* 565 * Another special case: if the last bound session ID was for a 566 * forwarding, and this function is not being called to check a sign 567 * request (i.e. no 'user' supplied), then only permit the key if 568 * there is a permission that would allow it to be used at another 569 * destination. This hides keys that are allowed to be used to 570 * authenticate *to* a host but not permitted for *use* beyond it. 571 */ 572 hks = &e->session_ids[e->nsession_ids - 1]; 573 if (hks->forwarded && user == NULL && 574 permitted_by_dest_constraints(hks->key, NULL, id, 575 NULL, NULL) != 0) { 576 debug3_f("key permitted at host but not after"); 577 return -1; 578 } 579 580 /* success */ 581 return 0; 582 } 583 584 static int 585 socket_is_remote(SocketEntry *e) 586 { 587 return e->session_bind_attempted || (e->nsession_ids != 0); 588 } 589 590 /* return matching private key for given public key */ 591 static Identity * 592 lookup_identity(struct sshkey *key) 593 { 594 Identity *id; 595 596 TAILQ_FOREACH(id, &idtab->idlist, next) { 597 if (sshkey_equal(key, id->key)) 598 return (id); 599 } 600 return (NULL); 601 } 602 603 /* Check confirmation of keysign request */ 604 static int 605 confirm_key(Identity *id, const char *extra) 606 { 607 char *p; 608 int ret = -1; 609 610 p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); 611 if (p != NULL && 612 ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s", 613 id->comment, p, 614 extra == NULL ? "" : "\n", extra == NULL ? "" : extra)) 615 ret = 0; 616 free(p); 617 618 return (ret); 619 } 620 621 static void 622 send_status_generic(SocketEntry *e, u_int code) 623 { 624 int r; 625 626 if ((r = sshbuf_put_u32(e->output, 1)) != 0 || 627 (r = sshbuf_put_u8(e->output, code)) != 0) 628 fatal_fr(r, "compose"); 629 } 630 631 static void 632 send_status(SocketEntry *e, int success) 633 { 634 send_status_generic(e, 635 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 636 } 637 638 /* send list of supported public keys to 'client' */ 639 static void 640 process_request_identities(SocketEntry *e) 641 { 642 Identity *id; 643 struct sshbuf *msg, *keys; 644 int r; 645 u_int i = 0, nentries = 0; 646 char *fp; 647 648 debug2_f("entering"); 649 650 if ((msg = sshbuf_new()) == NULL || (keys = sshbuf_new()) == NULL) 651 fatal_f("sshbuf_new failed"); 652 TAILQ_FOREACH(id, &idtab->idlist, next) { 653 if ((fp = sshkey_fingerprint(id->key, SSH_FP_HASH_DEFAULT, 654 SSH_FP_DEFAULT)) == NULL) 655 fatal_f("fingerprint failed"); 656 debug_f("key %u / %u: %s %s", i++, idtab->nentries, 657 sshkey_ssh_name(id->key), fp); 658 dump_dest_constraints(__func__, 659 id->dest_constraints, id->ndest_constraints); 660 free(fp); 661 /* identity not visible, don't include in response */ 662 if (identity_permitted(id, e, NULL, NULL, NULL) != 0) 663 continue; 664 if ((r = sshkey_puts(id->key, keys)) != 0 || 665 (r = sshbuf_put_cstring(keys, id->comment)) != 0) { 666 error_fr(r, "compose key/comment"); 667 continue; 668 } 669 nentries++; 670 } 671 debug2_f("replying with %u allowed of %u available keys", 672 nentries, idtab->nentries); 673 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || 674 (r = sshbuf_put_u32(msg, nentries)) != 0 || 675 (r = sshbuf_putb(msg, keys)) != 0) 676 fatal_fr(r, "compose"); 677 if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 678 fatal_fr(r, "enqueue"); 679 sshbuf_free(msg); 680 sshbuf_free(keys); 681 } 682 683 684 static char * 685 agent_decode_alg(struct sshkey *key, u_int flags) 686 { 687 if (key->type == KEY_RSA) { 688 if (flags & SSH_AGENT_RSA_SHA2_256) 689 return "rsa-sha2-256"; 690 else if (flags & SSH_AGENT_RSA_SHA2_512) 691 return "rsa-sha2-512"; 692 } else if (key->type == KEY_RSA_CERT) { 693 if (flags & SSH_AGENT_RSA_SHA2_256) 694 return "rsa-sha2-256-cert-v01@openssh.com"; 695 else if (flags & SSH_AGENT_RSA_SHA2_512) 696 return "rsa-sha2-512-cert-v01@openssh.com"; 697 } 698 return NULL; 699 } 700 701 /* 702 * Attempt to parse the contents of a buffer as a SSH publickey userauth 703 * request, checking its contents for consistency and matching the embedded 704 * key against the one that is being used for signing. 705 * Note: does not modify msg buffer. 706 * Optionally extract the username, session ID and/or hostkey from the request. 707 */ 708 static int 709 parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key, 710 char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp) 711 { 712 struct sshbuf *b = NULL, *sess_id = NULL; 713 char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL; 714 int r; 715 u_char t, sig_follows; 716 struct sshkey *mkey = NULL, *hostkey = NULL; 717 718 if (userp != NULL) 719 *userp = NULL; 720 if (sess_idp != NULL) 721 *sess_idp = NULL; 722 if (hostkeyp != NULL) 723 *hostkeyp = NULL; 724 if ((b = sshbuf_fromb(msg)) == NULL) 725 fatal_f("sshbuf_fromb"); 726 727 /* SSH userauth request */ 728 if ((r = sshbuf_froms(b, &sess_id)) != 0) 729 goto out; 730 if (sshbuf_len(sess_id) == 0) { 731 r = SSH_ERR_INVALID_FORMAT; 732 goto out; 733 } 734 if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */ 735 (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */ 736 (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */ 737 (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */ 738 (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */ 739 (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */ 740 (r = sshkey_froms(b, &mkey)) != 0) /* key */ 741 goto out; 742 if (t != SSH2_MSG_USERAUTH_REQUEST || 743 sig_follows != 1 || 744 strcmp(service, "ssh-connection") != 0 || 745 !sshkey_equal(expected_key, mkey) || 746 sshkey_type_from_name(pkalg) != expected_key->type) { 747 r = SSH_ERR_INVALID_FORMAT; 748 goto out; 749 } 750 if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) { 751 if ((r = sshkey_froms(b, &hostkey)) != 0) 752 goto out; 753 } else if (strcmp(method, "publickey") != 0) { 754 r = SSH_ERR_INVALID_FORMAT; 755 goto out; 756 } 757 if (sshbuf_len(b) != 0) { 758 r = SSH_ERR_INVALID_FORMAT; 759 goto out; 760 } 761 /* success */ 762 r = 0; 763 debug3_f("well formed userauth"); 764 if (userp != NULL) { 765 *userp = user; 766 user = NULL; 767 } 768 if (sess_idp != NULL) { 769 *sess_idp = sess_id; 770 sess_id = NULL; 771 } 772 if (hostkeyp != NULL) { 773 *hostkeyp = hostkey; 774 hostkey = NULL; 775 } 776 out: 777 sshbuf_free(b); 778 sshbuf_free(sess_id); 779 free(user); 780 free(service); 781 free(method); 782 free(pkalg); 783 sshkey_free(mkey); 784 sshkey_free(hostkey); 785 return r; 786 } 787 788 /* 789 * Attempt to parse the contents of a buffer as a SSHSIG signature request. 790 * Note: does not modify buffer. 791 */ 792 static int 793 parse_sshsig_request(struct sshbuf *msg) 794 { 795 int r; 796 struct sshbuf *b; 797 798 if ((b = sshbuf_fromb(msg)) == NULL) 799 fatal_f("sshbuf_fromb"); 800 801 if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 || 802 (r = sshbuf_consume(b, 6)) != 0 || 803 (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */ 804 (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */ 805 (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */ 806 (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */ 807 goto out; 808 if (sshbuf_len(b) != 0) { 809 r = SSH_ERR_INVALID_FORMAT; 810 goto out; 811 } 812 /* success */ 813 r = 0; 814 out: 815 sshbuf_free(b); 816 return r; 817 } 818 819 /* 820 * This function inspects a message to be signed by a FIDO key that has a 821 * web-like application string (i.e. one that does not begin with "ssh:". 822 * It checks that the message is one of those expected for SSH operations 823 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges 824 * for the web. 825 */ 826 static int 827 check_websafe_message_contents(struct sshkey *key, struct sshbuf *data) 828 { 829 if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) { 830 debug_f("signed data matches public key userauth request"); 831 return 1; 832 } 833 if (parse_sshsig_request(data) == 0) { 834 debug_f("signed data matches SSHSIG signature request"); 835 return 1; 836 } 837 838 /* XXX check CA signature operation */ 839 840 error("web-origin key attempting to sign non-SSH message"); 841 return 0; 842 } 843 844 static int 845 buf_equal(const struct sshbuf *a, const struct sshbuf *b) 846 { 847 if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL) 848 return SSH_ERR_INVALID_ARGUMENT; 849 if (sshbuf_len(a) != sshbuf_len(b)) 850 return SSH_ERR_INVALID_FORMAT; 851 if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0) 852 return SSH_ERR_INVALID_FORMAT; 853 return 0; 854 } 855 856 /* ssh2 only */ 857 static void 858 process_sign_request2(SocketEntry *e) 859 { 860 u_char *signature = NULL; 861 size_t slen = 0; 862 u_int compat = 0, flags; 863 int r, ok = -1, retried = 0; 864 char *fp = NULL, *pin = NULL, *prompt = NULL; 865 char *user = NULL, *sig_dest = NULL; 866 const char *fwd_host = NULL, *dest_host = NULL; 867 struct sshbuf *msg = NULL, *data = NULL, *sid = NULL; 868 struct sshkey *key = NULL, *hostkey = NULL; 869 struct identity *id; 870 struct notifier_ctx *notifier = NULL; 871 872 debug_f("entering"); 873 874 if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL) 875 fatal_f("sshbuf_new failed"); 876 if ((r = sshkey_froms(e->request, &key)) != 0 || 877 (r = sshbuf_get_stringb(e->request, data)) != 0 || 878 (r = sshbuf_get_u32(e->request, &flags)) != 0) { 879 error_fr(r, "parse"); 880 goto send; 881 } 882 883 if ((id = lookup_identity(key)) == NULL) { 884 verbose_f("%s key not found", sshkey_type(key)); 885 goto send; 886 } 887 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, 888 SSH_FP_DEFAULT)) == NULL) 889 fatal_f("fingerprint failed"); 890 891 if (id->ndest_constraints != 0) { 892 if (e->nsession_ids == 0) { 893 logit_f("refusing use of destination-constrained key " 894 "to sign on unbound connection"); 895 goto send; 896 } 897 if (parse_userauth_request(data, key, &user, &sid, 898 &hostkey) != 0) { 899 logit_f("refusing use of destination-constrained key " 900 "to sign an unidentified signature"); 901 goto send; 902 } 903 /* XXX logspam */ 904 debug_f("user=%s", user); 905 if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0) 906 goto send; 907 /* XXX display fwd_host/dest_host in askpass UI */ 908 /* 909 * Ensure that the session ID is the most recent one 910 * registered on the socket - it should have been bound by 911 * ssh immediately before userauth. 912 */ 913 if (buf_equal(sid, 914 e->session_ids[e->nsession_ids - 1].sid) != 0) { 915 error_f("unexpected session ID (%zu listed) on " 916 "signature request for target user %s with " 917 "key %s %s", e->nsession_ids, user, 918 sshkey_type(id->key), fp); 919 goto send; 920 } 921 /* 922 * Ensure that the hostkey embedded in the signature matches 923 * the one most recently bound to the socket. An exception is 924 * made for the initial forwarding hop. 925 */ 926 if (e->nsession_ids > 1 && hostkey == NULL) { 927 error_f("refusing use of destination-constrained key: " 928 "no hostkey recorded in signature for forwarded " 929 "connection"); 930 goto send; 931 } 932 if (hostkey != NULL && !sshkey_equal(hostkey, 933 e->session_ids[e->nsession_ids - 1].key)) { 934 error_f("refusing use of destination-constrained key: " 935 "mismatch between hostkey in request and most " 936 "recently bound session"); 937 goto send; 938 } 939 xasprintf(&sig_dest, "public key authentication request for " 940 "user \"%s\" to listed host", user); 941 } 942 if (id->confirm && confirm_key(id, sig_dest) != 0) { 943 verbose_f("user refused key"); 944 goto send; 945 } 946 if (sshkey_is_sk(id->key)) { 947 if (restrict_websafe && 948 match_pattern_list(id->key->sk_application, 949 websafe_allowlist, 0) != 1 && 950 !check_websafe_message_contents(key, data)) { 951 /* error already logged */ 952 goto send; 953 } 954 if (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { 955 notifier = notify_start(0, 956 "Confirm user presence for key %s %s%s%s", 957 sshkey_type(id->key), fp, 958 sig_dest == NULL ? "" : "\n", 959 sig_dest == NULL ? "" : sig_dest); 960 } 961 } 962 retry_pin: 963 if ((r = sshkey_sign(id->key, &signature, &slen, 964 sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags), 965 id->sk_provider, pin, compat)) != 0) { 966 debug_fr(r, "sshkey_sign"); 967 if (pin == NULL && !retried && sshkey_is_sk(id->key) && 968 r == SSH_ERR_KEY_WRONG_PASSPHRASE) { 969 notify_complete(notifier, NULL); 970 notifier = NULL; 971 /* XXX include sig_dest */ 972 xasprintf(&prompt, "Enter PIN%sfor %s key %s: ", 973 (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) ? 974 " and confirm user presence " : " ", 975 sshkey_type(id->key), fp); 976 pin = read_passphrase(prompt, RP_USE_ASKPASS); 977 retried = 1; 978 goto retry_pin; 979 } 980 error_fr(r, "sshkey_sign"); 981 goto send; 982 } 983 /* Success */ 984 ok = 0; 985 debug_f("good signature"); 986 send: 987 notify_complete(notifier, "User presence confirmed"); 988 989 if (ok == 0) { 990 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || 991 (r = sshbuf_put_string(msg, signature, slen)) != 0) 992 fatal_fr(r, "compose"); 993 } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) 994 fatal_fr(r, "compose failure"); 995 996 if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 997 fatal_fr(r, "enqueue"); 998 999 sshbuf_free(sid); 1000 sshbuf_free(data); 1001 sshbuf_free(msg); 1002 sshkey_free(key); 1003 sshkey_free(hostkey); 1004 free(fp); 1005 free(signature); 1006 free(sig_dest); 1007 free(user); 1008 free(prompt); 1009 if (pin != NULL) 1010 freezero(pin, strlen(pin)); 1011 } 1012 1013 /* shared */ 1014 static void 1015 process_remove_identity(SocketEntry *e) 1016 { 1017 int r, success = 0; 1018 struct sshkey *key = NULL; 1019 Identity *id; 1020 1021 debug2_f("entering"); 1022 if ((r = sshkey_froms(e->request, &key)) != 0) { 1023 error_fr(r, "parse key"); 1024 goto done; 1025 } 1026 if ((id = lookup_identity(key)) == NULL) { 1027 debug_f("key not found"); 1028 goto done; 1029 } 1030 /* identity not visible, cannot be removed */ 1031 if (identity_permitted(id, e, NULL, NULL, NULL) != 0) 1032 goto done; /* error already logged */ 1033 /* We have this key, free it. */ 1034 if (idtab->nentries < 1) 1035 fatal_f("internal error: nentries %d", idtab->nentries); 1036 TAILQ_REMOVE(&idtab->idlist, id, next); 1037 free_identity(id); 1038 idtab->nentries--; 1039 success = 1; 1040 done: 1041 sshkey_free(key); 1042 send_status(e, success); 1043 } 1044 1045 static void 1046 remove_all_identities(void) 1047 { 1048 Identity *id; 1049 1050 debug2_f("entering"); 1051 /* Loop over all identities and clear the keys. */ 1052 for (id = TAILQ_FIRST(&idtab->idlist); id; 1053 id = TAILQ_FIRST(&idtab->idlist)) { 1054 TAILQ_REMOVE(&idtab->idlist, id, next); 1055 free_identity(id); 1056 } 1057 1058 /* Mark that there are no identities. */ 1059 idtab->nentries = 0; 1060 } 1061 1062 static void 1063 process_remove_all_identities(SocketEntry *e) 1064 { 1065 remove_all_identities(); 1066 1067 /* Send success. */ 1068 send_status(e, 1); 1069 } 1070 1071 /* removes expired keys and returns number of seconds until the next expiry */ 1072 static time_t 1073 reaper(void) 1074 { 1075 time_t deadline = 0, now = monotime(); 1076 Identity *id, *nxt; 1077 1078 for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { 1079 nxt = TAILQ_NEXT(id, next); 1080 if (id->death == 0) 1081 continue; 1082 if (now >= id->death) { 1083 debug("expiring key '%s'", id->comment); 1084 TAILQ_REMOVE(&idtab->idlist, id, next); 1085 free_identity(id); 1086 idtab->nentries--; 1087 } else 1088 deadline = (deadline == 0) ? id->death : 1089 MINIMUM(deadline, id->death); 1090 } 1091 if (deadline == 0 || deadline <= now) 1092 return 0; 1093 else 1094 return (deadline - now); 1095 } 1096 1097 static int 1098 parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch) 1099 { 1100 u_char key_is_ca; 1101 size_t elen = 0, userlen = 0; 1102 int r; 1103 struct sshkey *k = NULL; 1104 char *fp; 1105 1106 memset(dch, '\0', sizeof(*dch)); 1107 if ((r = sshbuf_get_cstring(b, &dch->user, &userlen)) != 0 || 1108 (r = sshbuf_get_cstring(b, &dch->hostname, NULL)) != 0 || 1109 (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { 1110 error_fr(r, "parse"); 1111 goto out; 1112 } 1113 if (elen != 0) { 1114 error_f("unsupported extensions (len %zu)", elen); 1115 r = SSH_ERR_FEATURE_UNSUPPORTED; 1116 goto out; 1117 } 1118 if (*dch->hostname == '\0') { 1119 free(dch->hostname); 1120 dch->hostname = NULL; 1121 } 1122 if (*dch->user == '\0') { 1123 free(dch->user); 1124 dch->user = NULL; 1125 } else if (userlen > AGENT_USER_CONSTRAINT_MAX_LEN) { 1126 error_f("user match pattern too long"); 1127 r = SSH_ERR_INVALID_FORMAT; 1128 goto out; 1129 } 1130 while (sshbuf_len(b) != 0) { 1131 dch->keys = xrecallocarray(dch->keys, dch->nkeys, 1132 dch->nkeys + 1, sizeof(*dch->keys)); 1133 dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, 1134 dch->nkeys + 1, sizeof(*dch->key_is_ca)); 1135 if ((r = sshkey_froms(b, &k)) != 0 || 1136 (r = sshbuf_get_u8(b, &key_is_ca)) != 0) 1137 goto out; 1138 if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, 1139 SSH_FP_DEFAULT)) == NULL) 1140 fatal_f("fingerprint failed"); 1141 debug3_f("%s%s%s: adding %skey %s %s", 1142 dch->user == NULL ? "" : dch->user, 1143 dch->user == NULL ? "" : "@", 1144 dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp); 1145 free(fp); 1146 dch->keys[dch->nkeys] = k; 1147 dch->key_is_ca[dch->nkeys] = key_is_ca != 0; 1148 dch->nkeys++; 1149 k = NULL; /* transferred */ 1150 } 1151 /* success */ 1152 r = 0; 1153 out: 1154 sshkey_free(k); 1155 return r; 1156 } 1157 1158 static int 1159 parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc) 1160 { 1161 struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL; 1162 int r; 1163 size_t elen = 0; 1164 1165 debug3_f("entering"); 1166 1167 memset(dc, '\0', sizeof(*dc)); 1168 if ((r = sshbuf_froms(m, &b)) != 0 || 1169 (r = sshbuf_froms(b, &frombuf)) != 0 || 1170 (r = sshbuf_froms(b, &tobuf)) != 0 || 1171 (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { 1172 error_fr(r, "parse"); 1173 goto out; 1174 } 1175 if ((r = parse_dest_constraint_hop(frombuf, &dc->from)) != 0 || 1176 (r = parse_dest_constraint_hop(tobuf, &dc->to)) != 0) 1177 goto out; /* already logged */ 1178 if (elen != 0) { 1179 error_f("unsupported extensions (len %zu)", elen); 1180 r = SSH_ERR_FEATURE_UNSUPPORTED; 1181 goto out; 1182 } 1183 debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)", 1184 dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, 1185 dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", 1186 dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); 1187 /* check consistency */ 1188 if ((dc->from.hostname == NULL) != (dc->from.nkeys == 0) || 1189 dc->from.user != NULL) { 1190 error_f("inconsistent \"from\" specification"); 1191 r = SSH_ERR_INVALID_FORMAT; 1192 goto out; 1193 } 1194 if (dc->to.hostname == NULL || dc->to.nkeys == 0) { 1195 error_f("incomplete \"to\" specification"); 1196 r = SSH_ERR_INVALID_FORMAT; 1197 goto out; 1198 } 1199 /* success */ 1200 r = 0; 1201 out: 1202 sshbuf_free(b); 1203 sshbuf_free(frombuf); 1204 sshbuf_free(tobuf); 1205 return r; 1206 } 1207 1208 static int 1209 parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, 1210 struct dest_constraint **dcsp, size_t *ndcsp, int *cert_onlyp, 1211 struct sshkey ***certs, size_t *ncerts) 1212 { 1213 char *ext_name = NULL; 1214 int r; 1215 struct sshbuf *b = NULL; 1216 u_char v; 1217 struct sshkey *k; 1218 1219 if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { 1220 error_fr(r, "parse constraint extension"); 1221 goto out; 1222 } 1223 debug_f("constraint ext %s", ext_name); 1224 if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { 1225 if (sk_providerp == NULL) { 1226 error_f("%s not valid here", ext_name); 1227 r = SSH_ERR_INVALID_FORMAT; 1228 goto out; 1229 } 1230 if (*sk_providerp != NULL) { 1231 error_f("%s already set", ext_name); 1232 r = SSH_ERR_INVALID_FORMAT; 1233 goto out; 1234 } 1235 if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) { 1236 error_fr(r, "parse %s", ext_name); 1237 goto out; 1238 } 1239 } else if (strcmp(ext_name, 1240 "restrict-destination-v00@openssh.com") == 0) { 1241 if (*dcsp != NULL) { 1242 error_f("%s already set", ext_name); 1243 r = SSH_ERR_INVALID_FORMAT; 1244 goto out; 1245 } 1246 if ((r = sshbuf_froms(m, &b)) != 0) { 1247 error_fr(r, "parse %s outer", ext_name); 1248 goto out; 1249 } 1250 while (sshbuf_len(b) != 0) { 1251 if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { 1252 error_f("too many %s constraints", ext_name); 1253 r = SSH_ERR_INVALID_FORMAT; 1254 goto out; 1255 } 1256 *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, 1257 sizeof(**dcsp)); 1258 if ((r = parse_dest_constraint(b, 1259 *dcsp + (*ndcsp)++)) != 0) 1260 goto out; /* error already logged */ 1261 } 1262 } else if (strcmp(ext_name, 1263 "associated-certs-v00@openssh.com") == 0) { 1264 if (certs == NULL || ncerts == NULL || cert_onlyp == NULL) { 1265 error_f("%s not valid here", ext_name); 1266 r = SSH_ERR_INVALID_FORMAT; 1267 goto out; 1268 } 1269 if (*certs != NULL) { 1270 error_f("%s already set", ext_name); 1271 r = SSH_ERR_INVALID_FORMAT; 1272 goto out; 1273 } 1274 if ((r = sshbuf_get_u8(m, &v)) != 0 || 1275 (r = sshbuf_froms(m, &b)) != 0) { 1276 error_fr(r, "parse %s", ext_name); 1277 goto out; 1278 } 1279 *cert_onlyp = v != 0; 1280 while (sshbuf_len(b) != 0) { 1281 if (*ncerts >= AGENT_MAX_EXT_CERTS) { 1282 error_f("too many %s constraints", ext_name); 1283 r = SSH_ERR_INVALID_FORMAT; 1284 goto out; 1285 } 1286 *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, 1287 sizeof(**certs)); 1288 if ((r = sshkey_froms(b, &k)) != 0) { 1289 error_fr(r, "parse key"); 1290 goto out; 1291 } 1292 (*certs)[(*ncerts)++] = k; 1293 } 1294 } else { 1295 error_f("unsupported constraint \"%s\"", ext_name); 1296 r = SSH_ERR_FEATURE_UNSUPPORTED; 1297 goto out; 1298 } 1299 /* success */ 1300 r = 0; 1301 out: 1302 free(ext_name); 1303 sshbuf_free(b); 1304 return r; 1305 } 1306 1307 static int 1308 parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, 1309 u_int *secondsp, int *confirmp, char **sk_providerp, 1310 struct dest_constraint **dcsp, size_t *ndcsp, 1311 int *cert_onlyp, size_t *ncerts, struct sshkey ***certs) 1312 { 1313 u_char ctype; 1314 int r; 1315 u_int seconds; 1316 1317 while (sshbuf_len(m)) { 1318 if ((r = sshbuf_get_u8(m, &ctype)) != 0) { 1319 error_fr(r, "parse constraint type"); 1320 goto out; 1321 } 1322 switch (ctype) { 1323 case SSH_AGENT_CONSTRAIN_LIFETIME: 1324 if (*deathp != 0) { 1325 error_f("lifetime already set"); 1326 r = SSH_ERR_INVALID_FORMAT; 1327 goto out; 1328 } 1329 if ((r = sshbuf_get_u32(m, &seconds)) != 0) { 1330 error_fr(r, "parse lifetime constraint"); 1331 goto out; 1332 } 1333 *deathp = monotime() + seconds; 1334 *secondsp = seconds; 1335 break; 1336 case SSH_AGENT_CONSTRAIN_CONFIRM: 1337 if (*confirmp != 0) { 1338 error_f("confirm already set"); 1339 r = SSH_ERR_INVALID_FORMAT; 1340 goto out; 1341 } 1342 *confirmp = 1; 1343 break; 1344 case SSH_AGENT_CONSTRAIN_EXTENSION: 1345 if ((r = parse_key_constraint_extension(m, 1346 sk_providerp, dcsp, ndcsp, 1347 cert_onlyp, certs, ncerts)) != 0) 1348 goto out; /* error already logged */ 1349 break; 1350 default: 1351 error_f("Unknown constraint %d", ctype); 1352 r = SSH_ERR_FEATURE_UNSUPPORTED; 1353 goto out; 1354 } 1355 } 1356 /* success */ 1357 r = 0; 1358 out: 1359 return r; 1360 } 1361 1362 static void 1363 process_add_identity(SocketEntry *e) 1364 { 1365 Identity *id; 1366 int success = 0, confirm = 0; 1367 char *fp, *comment = NULL, *sk_provider = NULL; 1368 char canonical_provider[PATH_MAX]; 1369 time_t death = 0; 1370 u_int seconds = 0; 1371 struct dest_constraint *dest_constraints = NULL; 1372 size_t ndest_constraints = 0; 1373 struct sshkey *k = NULL; 1374 int r = SSH_ERR_INTERNAL_ERROR; 1375 1376 debug2_f("entering"); 1377 if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || 1378 k == NULL || 1379 (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { 1380 error_fr(r, "parse"); 1381 goto out; 1382 } 1383 if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, 1384 &sk_provider, &dest_constraints, &ndest_constraints, 1385 NULL, NULL, NULL) != 0) { 1386 error_f("failed to parse constraints"); 1387 sshbuf_reset(e->request); 1388 goto out; 1389 } 1390 dump_dest_constraints(__func__, dest_constraints, ndest_constraints); 1391 1392 if (sk_provider != NULL) { 1393 if (!sshkey_is_sk(k)) { 1394 error("Cannot add provider: %s is not an " 1395 "authenticator-hosted key", sshkey_type(k)); 1396 goto out; 1397 } 1398 if (strcasecmp(sk_provider, "internal") == 0) { 1399 debug_f("internal provider"); 1400 } else { 1401 if (socket_is_remote(e) && !remote_add_provider) { 1402 verbose("failed add of SK provider \"%.100s\": " 1403 "remote addition of providers is disabled", 1404 sk_provider); 1405 goto out; 1406 } 1407 if (realpath(sk_provider, canonical_provider) == NULL) { 1408 verbose("failed provider \"%.100s\": " 1409 "realpath: %s", sk_provider, 1410 strerror(errno)); 1411 goto out; 1412 } 1413 free(sk_provider); 1414 sk_provider = xstrdup(canonical_provider); 1415 if (match_pattern_list(sk_provider, 1416 allowed_providers, 0) != 1) { 1417 error("Refusing add key: " 1418 "provider %s not allowed", sk_provider); 1419 goto out; 1420 } 1421 } 1422 } 1423 if ((r = sshkey_shield_private(k)) != 0) { 1424 error_fr(r, "shield private"); 1425 goto out; 1426 } 1427 if (lifetime && !death) 1428 death = monotime() + lifetime; 1429 if ((id = lookup_identity(k)) == NULL) { 1430 id = xcalloc(1, sizeof(Identity)); 1431 TAILQ_INSERT_TAIL(&idtab->idlist, id, next); 1432 /* Increment the number of identities. */ 1433 idtab->nentries++; 1434 } else { 1435 /* identity not visible, do not update */ 1436 if (identity_permitted(id, e, NULL, NULL, NULL) != 0) 1437 goto out; /* error already logged */ 1438 /* key state might have been updated */ 1439 sshkey_free(id->key); 1440 free(id->comment); 1441 free(id->sk_provider); 1442 free_dest_constraints(id->dest_constraints, 1443 id->ndest_constraints); 1444 } 1445 /* success */ 1446 id->key = k; 1447 id->comment = comment; 1448 id->death = death; 1449 id->confirm = confirm; 1450 id->sk_provider = sk_provider; 1451 id->dest_constraints = dest_constraints; 1452 id->ndest_constraints = ndest_constraints; 1453 1454 if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, 1455 SSH_FP_DEFAULT)) == NULL) 1456 fatal_f("sshkey_fingerprint failed"); 1457 debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " 1458 "(provider: %s) (destination constraints: %zu)", 1459 sshkey_ssh_name(k), fp, comment, seconds, confirm, 1460 sk_provider == NULL ? "none" : sk_provider, ndest_constraints); 1461 free(fp); 1462 /* transferred */ 1463 k = NULL; 1464 comment = NULL; 1465 sk_provider = NULL; 1466 dest_constraints = NULL; 1467 ndest_constraints = 0; 1468 success = 1; 1469 out: 1470 free(sk_provider); 1471 free(comment); 1472 sshkey_free(k); 1473 free_dest_constraints(dest_constraints, ndest_constraints); 1474 send_status(e, success); 1475 } 1476 1477 /* XXX todo: encrypt sensitive data with passphrase */ 1478 static void 1479 process_lock_agent(SocketEntry *e, int lock) 1480 { 1481 int r, success = 0, delay; 1482 char *passwd; 1483 u_char passwdhash[LOCK_SIZE]; 1484 static u_int fail_count = 0; 1485 size_t pwlen; 1486 1487 debug2_f("entering"); 1488 /* 1489 * This is deliberately fatal: the user has requested that we lock, 1490 * but we can't parse their request properly. The only safe thing to 1491 * do is abort. 1492 */ 1493 if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0) 1494 fatal_fr(r, "parse"); 1495 if (pwlen == 0) { 1496 debug("empty password not supported"); 1497 } else if (locked && !lock) { 1498 if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), 1499 passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0) 1500 fatal("bcrypt_pbkdf"); 1501 if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) { 1502 debug("agent unlocked"); 1503 locked = 0; 1504 fail_count = 0; 1505 explicit_bzero(lock_pwhash, sizeof(lock_pwhash)); 1506 success = 1; 1507 } else { 1508 /* delay in 0.1s increments up to 10s */ 1509 if (fail_count < 100) 1510 fail_count++; 1511 delay = 100000 * fail_count; 1512 debug("unlock failed, delaying %0.1lf seconds", 1513 (double)delay/1000000); 1514 usleep(delay); 1515 } 1516 explicit_bzero(passwdhash, sizeof(passwdhash)); 1517 } else if (!locked && lock) { 1518 debug("agent locked"); 1519 locked = 1; 1520 arc4random_buf(lock_salt, sizeof(lock_salt)); 1521 if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), 1522 lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0) 1523 fatal("bcrypt_pbkdf"); 1524 success = 1; 1525 } 1526 freezero(passwd, pwlen); 1527 send_status(e, success); 1528 } 1529 1530 static void 1531 no_identities(SocketEntry *e) 1532 { 1533 struct sshbuf *msg; 1534 int r; 1535 1536 if ((msg = sshbuf_new()) == NULL) 1537 fatal_f("sshbuf_new failed"); 1538 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || 1539 (r = sshbuf_put_u32(msg, 0)) != 0 || 1540 (r = sshbuf_put_stringb(e->output, msg)) != 0) 1541 fatal_fr(r, "compose"); 1542 sshbuf_free(msg); 1543 } 1544 1545 #ifdef ENABLE_PKCS11 1546 /* Add an identity to idlist; takes ownership of 'key' and 'comment' */ 1547 static void 1548 add_p11_identity(struct sshkey *key, char *comment, const char *provider, 1549 time_t death, u_int confirm, struct dest_constraint *dest_constraints, 1550 size_t ndest_constraints) 1551 { 1552 Identity *id; 1553 1554 if (lookup_identity(key) != NULL) { 1555 sshkey_free(key); 1556 free(comment); 1557 return; 1558 } 1559 id = xcalloc(1, sizeof(Identity)); 1560 id->key = key; 1561 id->comment = comment; 1562 id->provider = xstrdup(provider); 1563 id->death = death; 1564 id->confirm = confirm; 1565 id->dest_constraints = dup_dest_constraints(dest_constraints, 1566 ndest_constraints); 1567 id->ndest_constraints = ndest_constraints; 1568 TAILQ_INSERT_TAIL(&idtab->idlist, id, next); 1569 idtab->nentries++; 1570 } 1571 1572 static void 1573 process_add_smartcard_key(SocketEntry *e) 1574 { 1575 char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; 1576 char **comments = NULL; 1577 int r, i, count = 0, success = 0, confirm = 0; 1578 u_int seconds = 0; 1579 time_t death = 0; 1580 struct sshkey **keys = NULL, *k; 1581 struct dest_constraint *dest_constraints = NULL; 1582 size_t j, ndest_constraints = 0, ncerts = 0; 1583 struct sshkey **certs = NULL; 1584 int cert_only = 0; 1585 1586 debug2_f("entering"); 1587 if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || 1588 (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { 1589 error_fr(r, "parse"); 1590 goto send; 1591 } 1592 if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, 1593 NULL, &dest_constraints, &ndest_constraints, &cert_only, 1594 &ncerts, &certs) != 0) { 1595 error_f("failed to parse constraints"); 1596 goto send; 1597 } 1598 dump_dest_constraints(__func__, dest_constraints, ndest_constraints); 1599 if (socket_is_remote(e) && !remote_add_provider) { 1600 verbose("failed PKCS#11 add of \"%.100s\": remote addition of " 1601 "providers is disabled", provider); 1602 goto send; 1603 } 1604 if (realpath(provider, canonical_provider) == NULL) { 1605 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", 1606 provider, strerror(errno)); 1607 goto send; 1608 } 1609 if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { 1610 verbose("refusing PKCS#11 add of \"%.100s\": " 1611 "provider not allowed", canonical_provider); 1612 goto send; 1613 } 1614 debug_f("add %.100s", canonical_provider); 1615 if (lifetime && !death) 1616 death = monotime() + lifetime; 1617 1618 count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); 1619 for (i = 0; i < count; i++) { 1620 if (comments[i] == NULL || comments[i][0] == '\0') { 1621 free(comments[i]); 1622 comments[i] = xstrdup(canonical_provider); 1623 } 1624 for (j = 0; j < ncerts; j++) { 1625 if (!sshkey_is_cert(certs[j])) 1626 continue; 1627 if (!sshkey_equal_public(keys[i], certs[j])) 1628 continue; 1629 if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) 1630 continue; 1631 add_p11_identity(k, xstrdup(comments[i]), 1632 canonical_provider, death, confirm, 1633 dest_constraints, ndest_constraints); 1634 success = 1; 1635 } 1636 if (!cert_only && lookup_identity(keys[i]) == NULL) { 1637 add_p11_identity(keys[i], comments[i], 1638 canonical_provider, death, confirm, 1639 dest_constraints, ndest_constraints); 1640 keys[i] = NULL; /* transferred */ 1641 comments[i] = NULL; /* transferred */ 1642 success = 1; 1643 } 1644 /* XXX update constraints for existing keys */ 1645 sshkey_free(keys[i]); 1646 free(comments[i]); 1647 } 1648 send: 1649 free(pin); 1650 free(provider); 1651 free(keys); 1652 free(comments); 1653 free_dest_constraints(dest_constraints, ndest_constraints); 1654 for (j = 0; j < ncerts; j++) 1655 sshkey_free(certs[j]); 1656 free(certs); 1657 send_status(e, success); 1658 } 1659 1660 static void 1661 process_remove_smartcard_key(SocketEntry *e) 1662 { 1663 char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; 1664 int r, success = 0; 1665 Identity *id, *nxt; 1666 1667 debug2_f("entering"); 1668 if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || 1669 (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { 1670 error_fr(r, "parse"); 1671 goto send; 1672 } 1673 free(pin); 1674 1675 if (realpath(provider, canonical_provider) == NULL) { 1676 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", 1677 provider, strerror(errno)); 1678 goto send; 1679 } 1680 1681 debug_f("remove %.100s", canonical_provider); 1682 for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { 1683 nxt = TAILQ_NEXT(id, next); 1684 /* Skip file--based keys */ 1685 if (id->provider == NULL) 1686 continue; 1687 if (!strcmp(canonical_provider, id->provider)) { 1688 TAILQ_REMOVE(&idtab->idlist, id, next); 1689 free_identity(id); 1690 idtab->nentries--; 1691 } 1692 } 1693 if (pkcs11_del_provider(canonical_provider) == 0) 1694 success = 1; 1695 else 1696 error_f("pkcs11_del_provider failed"); 1697 send: 1698 free(provider); 1699 send_status(e, success); 1700 } 1701 #endif /* ENABLE_PKCS11 */ 1702 1703 static int 1704 process_ext_session_bind(SocketEntry *e) 1705 { 1706 int r, sid_match, key_match; 1707 struct sshkey *key = NULL; 1708 struct sshbuf *sid = NULL, *sig = NULL; 1709 char *fp = NULL; 1710 size_t i; 1711 u_char fwd = 0; 1712 1713 debug2_f("entering"); 1714 e->session_bind_attempted = 1; 1715 if ((r = sshkey_froms(e->request, &key)) != 0 || 1716 (r = sshbuf_froms(e->request, &sid)) != 0 || 1717 (r = sshbuf_froms(e->request, &sig)) != 0 || 1718 (r = sshbuf_get_u8(e->request, &fwd)) != 0) { 1719 error_fr(r, "parse"); 1720 goto out; 1721 } 1722 if (sshbuf_len(sid) > AGENT_MAX_SID_LEN) { 1723 error_f("session ID too long"); 1724 goto out; 1725 } 1726 if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, 1727 SSH_FP_DEFAULT)) == NULL) 1728 fatal_f("fingerprint failed"); 1729 /* check signature with hostkey on session ID */ 1730 if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig), 1731 sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) { 1732 error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp); 1733 goto out; 1734 } 1735 /* check whether sid/key already recorded */ 1736 for (i = 0; i < e->nsession_ids; i++) { 1737 if (!e->session_ids[i].forwarded) { 1738 error_f("attempt to bind session ID to socket " 1739 "previously bound for authentication attempt"); 1740 r = -1; 1741 goto out; 1742 } 1743 sid_match = buf_equal(sid, e->session_ids[i].sid) == 0; 1744 key_match = sshkey_equal(key, e->session_ids[i].key); 1745 if (sid_match && key_match) { 1746 debug_f("session ID already recorded for %s %s", 1747 sshkey_type(key), fp); 1748 r = 0; 1749 goto out; 1750 } else if (sid_match) { 1751 error_f("session ID recorded against different key " 1752 "for %s %s", sshkey_type(key), fp); 1753 r = -1; 1754 goto out; 1755 } 1756 /* 1757 * new sid with previously-seen key can happen, e.g. multiple 1758 * connections to the same host. 1759 */ 1760 } 1761 /* record new key/sid */ 1762 if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { 1763 error_f("too many session IDs recorded"); 1764 r = -1; 1765 goto out; 1766 } 1767 e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, 1768 e->nsession_ids + 1, sizeof(*e->session_ids)); 1769 i = e->nsession_ids++; 1770 debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i, 1771 AGENT_MAX_SESSION_IDS); 1772 e->session_ids[i].key = key; 1773 e->session_ids[i].forwarded = fwd != 0; 1774 key = NULL; /* transferred */ 1775 /* can't transfer sid; it's refcounted and scoped to request's life */ 1776 if ((e->session_ids[i].sid = sshbuf_new()) == NULL) 1777 fatal_f("sshbuf_new"); 1778 if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0) 1779 fatal_fr(r, "sshbuf_putb session ID"); 1780 /* success */ 1781 r = 0; 1782 out: 1783 free(fp); 1784 sshkey_free(key); 1785 sshbuf_free(sid); 1786 sshbuf_free(sig); 1787 return r == 0 ? 1 : 0; 1788 } 1789 1790 static int 1791 process_ext_query(SocketEntry *e) 1792 { 1793 int r; 1794 struct sshbuf *msg = NULL; 1795 1796 debug2_f("entering"); 1797 if ((msg = sshbuf_new()) == NULL) 1798 fatal_f("sshbuf_new failed"); 1799 if ((r = sshbuf_put_u8(msg, SSH_AGENT_EXTENSION_RESPONSE)) != 0 || 1800 (r = sshbuf_put_cstring(msg, "query")) != 0 || 1801 /* string[] supported extension types */ 1802 (r = sshbuf_put_cstring(msg, "session-bind@openssh.com")) != 0) 1803 fatal_fr(r, "compose"); 1804 if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 1805 fatal_fr(r, "enqueue"); 1806 sshbuf_free(msg); 1807 return 1; 1808 } 1809 1810 static void 1811 process_extension(SocketEntry *e) 1812 { 1813 int r, replied = 0, success = 0; 1814 char *name; 1815 1816 debug2_f("entering"); 1817 if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) { 1818 error_fr(r, "parse"); 1819 send_status(e, 0); 1820 return; 1821 } 1822 1823 if (strcmp(name, "query") == 0) 1824 replied = success = process_ext_query(e); 1825 else if (strcmp(name, "session-bind@openssh.com") == 0) 1826 success = process_ext_session_bind(e); 1827 else { 1828 debug_f("unsupported extension \"%s\"", name); 1829 free(name); 1830 send_status(e, 0); 1831 return; 1832 } 1833 free(name); 1834 /* Agent failures are signalled with a different error code */ 1835 if (!replied) { 1836 send_status_generic(e, 1837 success ? SSH_AGENT_SUCCESS : SSH_AGENT_EXTENSION_FAILURE); 1838 } 1839 } 1840 1841 /* 1842 * dispatch incoming message. 1843 * returns 1 on success, 0 for incomplete messages or -1 on error. 1844 */ 1845 static int 1846 process_message(u_int socknum) 1847 { 1848 u_int msg_len; 1849 u_char type; 1850 const u_char *cp; 1851 int r; 1852 SocketEntry *e; 1853 1854 if (socknum >= sockets_alloc) 1855 fatal_f("sock %u >= allocated %u", socknum, sockets_alloc); 1856 e = &sockets[socknum]; 1857 1858 if (sshbuf_len(e->input) < 5) 1859 return 0; /* Incomplete message header. */ 1860 cp = sshbuf_ptr(e->input); 1861 msg_len = PEEK_U32(cp); 1862 if (msg_len > AGENT_MAX_LEN) { 1863 debug_f("socket %u (fd=%d) message too long %u > %u", 1864 socknum, e->fd, msg_len, AGENT_MAX_LEN); 1865 return -1; 1866 } 1867 if (sshbuf_len(e->input) < msg_len + 4) 1868 return 0; /* Incomplete message body. */ 1869 1870 /* move the current input to e->request */ 1871 sshbuf_reset(e->request); 1872 if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || 1873 (r = sshbuf_get_u8(e->request, &type)) != 0) { 1874 if (r == SSH_ERR_MESSAGE_INCOMPLETE || 1875 r == SSH_ERR_STRING_TOO_LARGE) { 1876 error_fr(r, "parse"); 1877 return -1; 1878 } 1879 fatal_fr(r, "parse"); 1880 } 1881 1882 debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type); 1883 1884 /* check whether agent is locked */ 1885 if (locked && type != SSH_AGENTC_UNLOCK) { 1886 sshbuf_reset(e->request); 1887 switch (type) { 1888 case SSH2_AGENTC_REQUEST_IDENTITIES: 1889 /* send empty lists */ 1890 no_identities(e); 1891 break; 1892 default: 1893 /* send a fail message for all other request types */ 1894 send_status(e, 0); 1895 } 1896 return 1; 1897 } 1898 1899 switch (type) { 1900 case SSH_AGENTC_LOCK: 1901 case SSH_AGENTC_UNLOCK: 1902 process_lock_agent(e, type == SSH_AGENTC_LOCK); 1903 break; 1904 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 1905 process_remove_all_identities(e); /* safe for !WITH_SSH1 */ 1906 break; 1907 /* ssh2 */ 1908 case SSH2_AGENTC_SIGN_REQUEST: 1909 process_sign_request2(e); 1910 break; 1911 case SSH2_AGENTC_REQUEST_IDENTITIES: 1912 process_request_identities(e); 1913 break; 1914 case SSH2_AGENTC_ADD_IDENTITY: 1915 case SSH2_AGENTC_ADD_ID_CONSTRAINED: 1916 process_add_identity(e); 1917 break; 1918 case SSH2_AGENTC_REMOVE_IDENTITY: 1919 process_remove_identity(e); 1920 break; 1921 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: 1922 process_remove_all_identities(e); 1923 break; 1924 #ifdef ENABLE_PKCS11 1925 case SSH_AGENTC_ADD_SMARTCARD_KEY: 1926 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: 1927 process_add_smartcard_key(e); 1928 break; 1929 case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 1930 process_remove_smartcard_key(e); 1931 break; 1932 #endif /* ENABLE_PKCS11 */ 1933 case SSH_AGENTC_EXTENSION: 1934 process_extension(e); 1935 break; 1936 default: 1937 /* Unknown message. Respond with failure. */ 1938 error("Unknown message %d", type); 1939 sshbuf_reset(e->request); 1940 send_status(e, 0); 1941 break; 1942 } 1943 return 1; 1944 } 1945 1946 static void 1947 new_socket(sock_type type, int fd) 1948 { 1949 u_int i, old_alloc, new_alloc; 1950 1951 debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" : 1952 (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN")); 1953 if (type == AUTH_CONNECTION) { 1954 debug("xcount %d -> %d", xcount, xcount + 1); 1955 ++xcount; 1956 } 1957 set_nonblock(fd); 1958 1959 if (fd > max_fd) 1960 max_fd = fd; 1961 1962 for (i = 0; i < sockets_alloc; i++) 1963 if (sockets[i].type == AUTH_UNUSED) { 1964 sockets[i].fd = fd; 1965 if ((sockets[i].input = sshbuf_new()) == NULL || 1966 (sockets[i].output = sshbuf_new()) == NULL || 1967 (sockets[i].request = sshbuf_new()) == NULL) 1968 fatal_f("sshbuf_new failed"); 1969 sockets[i].type = type; 1970 return; 1971 } 1972 old_alloc = sockets_alloc; 1973 new_alloc = sockets_alloc + 10; 1974 sockets = xrecallocarray(sockets, old_alloc, new_alloc, 1975 sizeof(sockets[0])); 1976 for (i = old_alloc; i < new_alloc; i++) 1977 sockets[i].type = AUTH_UNUSED; 1978 sockets_alloc = new_alloc; 1979 sockets[old_alloc].fd = fd; 1980 if ((sockets[old_alloc].input = sshbuf_new()) == NULL || 1981 (sockets[old_alloc].output = sshbuf_new()) == NULL || 1982 (sockets[old_alloc].request = sshbuf_new()) == NULL) 1983 fatal_f("sshbuf_new failed"); 1984 sockets[old_alloc].type = type; 1985 } 1986 1987 static int 1988 handle_socket_read(u_int socknum) 1989 { 1990 struct sockaddr_un sunaddr; 1991 socklen_t slen; 1992 uid_t euid; 1993 gid_t egid; 1994 int fd; 1995 1996 slen = sizeof(sunaddr); 1997 fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen); 1998 if (fd == -1) { 1999 error("accept from AUTH_SOCKET: %s", strerror(errno)); 2000 return -1; 2001 } 2002 if (getpeereid(fd, &euid, &egid) == -1) { 2003 error("getpeereid %d failed: %s", fd, strerror(errno)); 2004 close(fd); 2005 return -1; 2006 } 2007 if ((euid != 0) && (getuid() != euid)) { 2008 error("uid mismatch: peer euid %u != uid %u", 2009 (u_int) euid, (u_int) getuid()); 2010 close(fd); 2011 return -1; 2012 } 2013 new_socket(AUTH_CONNECTION, fd); 2014 return 0; 2015 } 2016 2017 static int 2018 handle_conn_read(u_int socknum) 2019 { 2020 char buf[AGENT_RBUF_LEN]; 2021 ssize_t len; 2022 int r; 2023 2024 if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) { 2025 if (len == -1) { 2026 if (errno == EAGAIN || errno == EINTR) 2027 return 0; 2028 error_f("read error on socket %u (fd %d): %s", 2029 socknum, sockets[socknum].fd, strerror(errno)); 2030 } 2031 return -1; 2032 } 2033 if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0) 2034 fatal_fr(r, "compose"); 2035 explicit_bzero(buf, sizeof(buf)); 2036 for (;;) { 2037 if ((r = process_message(socknum)) == -1) 2038 return -1; 2039 else if (r == 0) 2040 break; 2041 } 2042 return 0; 2043 } 2044 2045 static int 2046 handle_conn_write(u_int socknum) 2047 { 2048 ssize_t len; 2049 int r; 2050 2051 if (sshbuf_len(sockets[socknum].output) == 0) 2052 return 0; /* shouldn't happen */ 2053 if ((len = write(sockets[socknum].fd, 2054 sshbuf_ptr(sockets[socknum].output), 2055 sshbuf_len(sockets[socknum].output))) <= 0) { 2056 if (len == -1) { 2057 if (errno == EAGAIN || errno == EINTR) 2058 return 0; 2059 error_f("read error on socket %u (fd %d): %s", 2060 socknum, sockets[socknum].fd, strerror(errno)); 2061 } 2062 return -1; 2063 } 2064 if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0) 2065 fatal_fr(r, "consume"); 2066 return 0; 2067 } 2068 2069 static void 2070 after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds) 2071 { 2072 size_t i; 2073 u_int socknum, activefds = npfd; 2074 2075 for (i = 0; i < npfd; i++) { 2076 if (pfd[i].revents == 0) 2077 continue; 2078 /* Find sockets entry */ 2079 for (socknum = 0; socknum < sockets_alloc; socknum++) { 2080 if (sockets[socknum].type != AUTH_SOCKET && 2081 sockets[socknum].type != AUTH_CONNECTION) 2082 continue; 2083 if (pfd[i].fd == sockets[socknum].fd) 2084 break; 2085 } 2086 if (socknum >= sockets_alloc) { 2087 error_f("no socket for fd %d", pfd[i].fd); 2088 continue; 2089 } 2090 /* Process events */ 2091 switch (sockets[socknum].type) { 2092 case AUTH_SOCKET: 2093 if ((pfd[i].revents & (POLLIN|POLLERR)) == 0) 2094 break; 2095 if (npfd > maxfds) { 2096 debug3("out of fds (active %u >= limit %u); " 2097 "skipping accept", activefds, maxfds); 2098 break; 2099 } 2100 if (handle_socket_read(socknum) == 0) 2101 activefds++; 2102 break; 2103 case AUTH_CONNECTION: 2104 if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) != 0 && 2105 handle_conn_read(socknum) != 0) 2106 goto close_sock; 2107 if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 && 2108 handle_conn_write(socknum) != 0) { 2109 close_sock: 2110 if (activefds == 0) 2111 fatal("activefds == 0 at close_sock"); 2112 close_socket(&sockets[socknum]); 2113 activefds--; 2114 break; 2115 } 2116 break; 2117 default: 2118 break; 2119 } 2120 } 2121 } 2122 2123 static int 2124 prepare_poll(struct pollfd **pfdp, size_t *npfdp, struct timespec *timeoutp, u_int maxfds) 2125 { 2126 struct pollfd *pfd = *pfdp; 2127 size_t i, j, npfd = 0; 2128 time_t deadline; 2129 int r; 2130 2131 /* Count active sockets */ 2132 for (i = 0; i < sockets_alloc; i++) { 2133 switch (sockets[i].type) { 2134 case AUTH_SOCKET: 2135 case AUTH_CONNECTION: 2136 npfd++; 2137 break; 2138 case AUTH_UNUSED: 2139 break; 2140 default: 2141 fatal("Unknown socket type %d", sockets[i].type); 2142 break; 2143 } 2144 } 2145 if (npfd != *npfdp && 2146 (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL) 2147 fatal_f("recallocarray failed"); 2148 *pfdp = pfd; 2149 *npfdp = npfd; 2150 2151 for (i = j = 0; i < sockets_alloc; i++) { 2152 switch (sockets[i].type) { 2153 case AUTH_SOCKET: 2154 if (npfd > maxfds) { 2155 debug3("out of fds (active %zu >= limit %u); " 2156 "skipping arming listener", npfd, maxfds); 2157 break; 2158 } 2159 pfd[j].fd = sockets[i].fd; 2160 pfd[j].revents = 0; 2161 pfd[j].events = POLLIN; 2162 j++; 2163 break; 2164 case AUTH_CONNECTION: 2165 pfd[j].fd = sockets[i].fd; 2166 pfd[j].revents = 0; 2167 /* 2168 * Only prepare to read if we can handle a full-size 2169 * input read buffer and enqueue a max size reply.. 2170 */ 2171 if ((r = sshbuf_check_reserve(sockets[i].input, 2172 AGENT_RBUF_LEN)) == 0 && 2173 (r = sshbuf_check_reserve(sockets[i].output, 2174 AGENT_MAX_LEN)) == 0) 2175 pfd[j].events = POLLIN; 2176 else if (r != SSH_ERR_NO_BUFFER_SPACE) 2177 fatal_fr(r, "reserve"); 2178 if (sshbuf_len(sockets[i].output) > 0) 2179 pfd[j].events |= POLLOUT; 2180 j++; 2181 break; 2182 default: 2183 break; 2184 } 2185 } 2186 deadline = reaper(); 2187 if (parent_alive_interval != 0) 2188 deadline = (deadline == 0) ? parent_alive_interval : 2189 MINIMUM(deadline, parent_alive_interval); 2190 if (deadline != 0) 2191 ptimeout_deadline_sec(timeoutp, deadline); 2192 return (1); 2193 } 2194 2195 static void 2196 cleanup_socket(void) 2197 { 2198 if (cleanup_pid != 0 && getpid() != cleanup_pid) 2199 return; 2200 debug_f("cleanup"); 2201 if (socket_name != NULL) { 2202 unlink(socket_name); 2203 free(socket_name); 2204 socket_name = NULL; 2205 } 2206 if (socket_dir[0]) 2207 rmdir(socket_dir); 2208 } 2209 2210 void 2211 cleanup_exit(int i) 2212 { 2213 cleanup_socket(); 2214 #ifdef ENABLE_PKCS11 2215 pkcs11_terminate(); 2216 #endif 2217 _exit(i); 2218 } 2219 2220 static void 2221 cleanup_handler(int sig) 2222 { 2223 signalled_exit = sig; 2224 } 2225 2226 static void 2227 keydrop_handler(int sig) 2228 { 2229 signalled_keydrop = sig; 2230 } 2231 2232 static void 2233 check_parent_exists(void) 2234 { 2235 /* 2236 * If our parent has exited then getppid() will return (pid_t)1, 2237 * so testing for that should be safe. 2238 */ 2239 if (parent_pid != -1 && getppid() != parent_pid) { 2240 /* printf("Parent has died - Authentication agent exiting.\n"); */ 2241 cleanup_socket(); 2242 _exit(2); 2243 } 2244 } 2245 2246 static void 2247 usage(void) 2248 { 2249 fprintf(stderr, 2250 "usage: ssh-agent [-c | -s] [-DdTUx] [-a bind_address] [-E fingerprint_hash]\n" 2251 " [-O option] [-P allowed_providers] [-t life]\n" 2252 " ssh-agent [-TU] [-a bind_address] [-E fingerprint_hash] [-O option]\n" 2253 " [-P allowed_providers] [-t life] command [arg ...]\n" 2254 " ssh-agent [-c | -s] -k\n" 2255 " ssh-agent -u\n" 2256 " ssh-agent -V\n"); 2257 exit(1); 2258 } 2259 2260 int 2261 main(int ac, char **av) 2262 { 2263 int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0; 2264 int s_flag = 0, T_flag = 0, u_flag = 0, U_flag = 0; 2265 int sock = -1, ch, result, saved_errno; 2266 pid_t pid; 2267 char *homedir = NULL, *shell, *format, *pidstr, *agentsocket = NULL; 2268 char *cp, pidstrbuf[1 + 3 * sizeof pid]; 2269 char *fdstr; 2270 const char *errstr = NULL; 2271 const char *ccp; 2272 #ifdef HAVE_SETRLIMIT 2273 struct rlimit rlim; 2274 #endif 2275 extern int optind; 2276 extern char *optarg; 2277 size_t len; 2278 mode_t prev_mask; 2279 struct timespec timeout; 2280 struct pollfd *pfd = NULL; 2281 size_t npfd = 0; 2282 u_int maxfds; 2283 sigset_t nsigset, osigset; 2284 int socket_activated = 0; 2285 2286 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 2287 sanitise_stdfd(); 2288 2289 /* drop */ 2290 (void)setegid(getgid()); 2291 (void)setgid(getgid()); 2292 setuid(geteuid()); 2293 2294 platform_disable_tracing(0); /* strict=no */ 2295 2296 #ifdef RLIMIT_NOFILE 2297 if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) 2298 fatal("%s: getrlimit: %s", __progname, strerror(errno)); 2299 #endif 2300 2301 __progname = ssh_get_progname(av[0]); 2302 seed_rng(); 2303 2304 while ((ch = getopt(ac, av, "cDdksTuUVxE:a:O:P:t:")) != -1) { 2305 switch (ch) { 2306 case 'E': 2307 fingerprint_hash = ssh_digest_alg_by_name(optarg); 2308 if (fingerprint_hash == -1) 2309 fatal("Invalid hash algorithm \"%s\"", optarg); 2310 break; 2311 case 'c': 2312 if (s_flag) 2313 usage(); 2314 c_flag++; 2315 break; 2316 case 'k': 2317 k_flag++; 2318 break; 2319 case 'O': 2320 if (strcmp(optarg, "no-restrict-websafe") == 0) 2321 restrict_websafe = 0; 2322 else if (strcmp(optarg, "allow-remote-pkcs11") == 0) 2323 remote_add_provider = 1; 2324 else if ((ccp = strprefix(optarg, 2325 "websafe-allow=", 0)) != NULL) { 2326 if (websafe_allowlist != NULL) 2327 fatal("websafe-allow already set"); 2328 websafe_allowlist = xstrdup(ccp); 2329 } else 2330 fatal("Unknown -O option"); 2331 break; 2332 case 'P': 2333 if (allowed_providers != NULL) 2334 fatal("-P option already specified"); 2335 allowed_providers = xstrdup(optarg); 2336 break; 2337 case 's': 2338 if (c_flag) 2339 usage(); 2340 s_flag++; 2341 break; 2342 case 'd': 2343 if (d_flag || D_flag) 2344 usage(); 2345 d_flag++; 2346 break; 2347 case 'D': 2348 if (d_flag || D_flag) 2349 usage(); 2350 D_flag++; 2351 break; 2352 case 'a': 2353 agentsocket = optarg; 2354 break; 2355 case 't': 2356 if ((lifetime = convtime(optarg)) == -1) { 2357 fprintf(stderr, "Invalid lifetime\n"); 2358 usage(); 2359 } 2360 break; 2361 case 'T': 2362 T_flag++; 2363 break; 2364 case 'u': 2365 u_flag++; 2366 break; 2367 case 'U': 2368 U_flag++; 2369 break; 2370 case 'V': 2371 fprintf(stderr, "%s, %s\n", 2372 SSH_VERSION, SSH_OPENSSL_VERSION); 2373 exit(0); 2374 case 'x': 2375 xcount = 0; 2376 break; 2377 default: 2378 usage(); 2379 } 2380 } 2381 ac -= optind; 2382 av += optind; 2383 2384 if (ac > 0 && 2385 (c_flag || k_flag || s_flag || d_flag || D_flag || u_flag)) 2386 usage(); 2387 2388 log_init(__progname, 2389 d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, 2390 SYSLOG_FACILITY_AUTH, 1); 2391 2392 if (allowed_providers == NULL) 2393 allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS); 2394 if (websafe_allowlist == NULL) 2395 websafe_allowlist = xstrdup(DEFAULT_WEBSAFE_ALLOWLIST); 2396 2397 if (ac == 0 && !c_flag && !s_flag) { 2398 shell = getenv("SHELL"); 2399 if (shell != NULL && (len = strlen(shell)) > 2 && 2400 strncmp(shell + len - 3, "csh", 3) == 0) 2401 c_flag = 1; 2402 } 2403 if (k_flag) { 2404 pidstr = getenv(SSH_AGENTPID_ENV_NAME); 2405 if (pidstr == NULL) { 2406 fprintf(stderr, "%s not set, cannot kill agent\n", 2407 SSH_AGENTPID_ENV_NAME); 2408 exit(1); 2409 } 2410 pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); 2411 if (errstr) { 2412 fprintf(stderr, 2413 "%s=\"%s\", which is not a good PID: %s\n", 2414 SSH_AGENTPID_ENV_NAME, pidstr, errstr); 2415 exit(1); 2416 } 2417 if (kill(pid, SIGTERM) == -1) { 2418 perror("kill"); 2419 exit(1); 2420 } 2421 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; 2422 printf(format, SSH_AUTHSOCKET_ENV_NAME); 2423 printf(format, SSH_AGENTPID_ENV_NAME); 2424 printf("echo Agent pid %ld killed;\n", (long)pid); 2425 exit(0); 2426 } 2427 if (u_flag) { 2428 if ((homedir = get_homedir()) == NULL) 2429 fatal("Couldn't determine home directory"); 2430 agent_cleanup_stale(homedir, u_flag > 1); 2431 printf("Deleted stale agent sockets in ~/%s\n", 2432 _PATH_SSH_AGENT_SOCKET_DIR); 2433 exit(0); 2434 } 2435 2436 /* 2437 * Minimum file descriptors: 2438 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) + 2439 * a few spare for libc / stack protectors / sanitisers, etc. 2440 */ 2441 #define SSH_AGENT_MIN_FDS (3+1+1+1+4) 2442 if (rlim.rlim_cur < SSH_AGENT_MIN_FDS) 2443 fatal("%s: file descriptor rlimit %lld too low (minimum %u)", 2444 __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS); 2445 maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS; 2446 2447 parent_pid = getpid(); 2448 2449 /* Has the socket been provided via socket activation? */ 2450 if (agentsocket == NULL && ac == 0 && (d_flag || D_flag) && 2451 (pidstr = getenv("LISTEN_PID")) != NULL && 2452 (fdstr = getenv("LISTEN_FDS")) != NULL) { 2453 if (strcmp(fdstr, "1") != 0) { 2454 fatal("unexpected LISTEN_FDS contents " 2455 "(want: \"1\" got\"%s\"", fdstr); 2456 } 2457 if (fcntl(3, F_GETFL) == -1) 2458 fatal("LISTEN_FDS set but fd 3 unavailable"); 2459 pid = (int)strtonum(pidstr, 1, INT_MAX, &errstr); 2460 if (errstr != NULL) 2461 fatal("invalid LISTEN_PID: %s", errstr); 2462 if (pid != getpid()) 2463 fatal("bad LISTEN_PID: %d vs pid %d", pid, getpid()); 2464 debug("using socket activation on fd=3"); 2465 sock = 3; 2466 socket_activated = 1; 2467 } 2468 2469 if (sock == -1 && agentsocket == NULL && !T_flag) { 2470 /* Default case: ~/.ssh/agent/[socket] */ 2471 if ((homedir = get_homedir()) == NULL) 2472 fatal("Couldn't determine home directory"); 2473 if (!U_flag) 2474 agent_cleanup_stale(homedir, 0); 2475 if (agent_listener(homedir, "agent", &sock, &socket_name) != 0) 2476 fatal_f("Couldn't prepare agent socket"); 2477 free(homedir); 2478 } else if (sock == -1) { 2479 if (T_flag) { 2480 /* 2481 * Create private directory for agent socket 2482 * in $TMPDIR. 2483 */ 2484 mktemp_proto(socket_dir, sizeof(socket_dir)); 2485 if (mkdtemp(socket_dir) == NULL) { 2486 perror("mkdtemp: private socket dir"); 2487 exit(1); 2488 } 2489 xasprintf(&socket_name, "%s/agent.%ld", 2490 socket_dir, (long)parent_pid); 2491 } else { 2492 /* Try to use specified agent socket */ 2493 socket_dir[0] = '\0'; 2494 socket_name = xstrdup(agentsocket); 2495 } 2496 /* Listen on socket */ 2497 prev_mask = umask(0177); 2498 if ((sock = unix_listener(socket_name, 2499 SSH_LISTEN_BACKLOG, 0)) < 0) { 2500 *socket_name = '\0'; /* Don't unlink existing file */ 2501 cleanup_exit(1); 2502 } 2503 umask(prev_mask); 2504 } 2505 2506 closefrom(sock == -1 ? STDERR_FILENO + 1 : sock + 1); 2507 2508 /* 2509 * Create socket early so it will exist before command gets run from 2510 * the parent. 2511 */ 2512 if (sock == -1) { 2513 prev_mask = umask(0177); 2514 sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); 2515 if (sock < 0) { 2516 /* XXX - unix_listener() calls error() not perror() */ 2517 *socket_name = '\0'; /* Don't unlink existing file */ 2518 cleanup_exit(1); 2519 } 2520 umask(prev_mask); 2521 } 2522 2523 /* 2524 * Fork, and have the parent execute the command, if any, or present 2525 * the socket data. The child continues as the authentication agent. 2526 */ 2527 if (D_flag || d_flag) { 2528 log_init(__progname, 2529 d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, 2530 SYSLOG_FACILITY_AUTH, 1); 2531 if (socket_name != NULL) { 2532 cp = argv_assemble(1, &socket_name); 2533 format = c_flag ? 2534 "setenv %s %s;\n" : "%s=%s; export %s;\n"; 2535 printf(format, SSH_AUTHSOCKET_ENV_NAME, cp, 2536 SSH_AUTHSOCKET_ENV_NAME); 2537 free(cp); 2538 printf("echo Agent pid %ld;\n", (long)parent_pid); 2539 fflush(stdout); 2540 } 2541 goto skip; 2542 } 2543 pid = fork(); 2544 if (pid == -1) { 2545 perror("fork"); 2546 cleanup_exit(1); 2547 } 2548 if (pid != 0) { /* Parent - execute the given command. */ 2549 close(sock); 2550 snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); 2551 if (ac == 0) { 2552 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 2553 cp = argv_assemble(1, &socket_name); 2554 printf(format, SSH_AUTHSOCKET_ENV_NAME, cp, 2555 SSH_AUTHSOCKET_ENV_NAME); 2556 printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, 2557 SSH_AGENTPID_ENV_NAME); 2558 free(cp); 2559 printf("echo Agent pid %ld;\n", (long)pid); 2560 exit(0); 2561 } 2562 if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || 2563 setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { 2564 perror("setenv"); 2565 exit(1); 2566 } 2567 execvp(av[0], av); 2568 perror(av[0]); 2569 exit(1); 2570 } 2571 /* child */ 2572 log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); 2573 2574 if (setsid() == -1) { 2575 error("setsid: %s", strerror(errno)); 2576 cleanup_exit(1); 2577 } 2578 2579 (void)chdir("/"); 2580 if (stdfd_devnull(1, 1, 1) == -1) 2581 error_f("stdfd_devnull failed"); 2582 2583 #ifdef HAVE_SETRLIMIT 2584 /* deny core dumps, since memory contains unencrypted private keys */ 2585 rlim.rlim_cur = rlim.rlim_max = 0; 2586 if (setrlimit(RLIMIT_CORE, &rlim) == -1) { 2587 error("setrlimit RLIMIT_CORE: %s", strerror(errno)); 2588 cleanup_exit(1); 2589 } 2590 #endif 2591 2592 skip: 2593 2594 cleanup_pid = getpid(); 2595 2596 #ifdef ENABLE_PKCS11 2597 pkcs11_init(0); 2598 #endif 2599 new_socket(AUTH_SOCKET, sock); 2600 if (ac > 0) 2601 parent_alive_interval = 10; 2602 idtab_init(); 2603 ssh_signal(SIGPIPE, SIG_IGN); 2604 ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN); 2605 ssh_signal(SIGHUP, cleanup_handler); 2606 ssh_signal(SIGTERM, cleanup_handler); 2607 ssh_signal(SIGUSR1, keydrop_handler); 2608 2609 sigemptyset(&nsigset); 2610 sigaddset(&nsigset, SIGINT); 2611 sigaddset(&nsigset, SIGHUP); 2612 sigaddset(&nsigset, SIGTERM); 2613 sigaddset(&nsigset, SIGUSR1); 2614 2615 if (socket_name != NULL && unveil(socket_name, "c") == -1) { 2616 fatal("%s: unveil %s %s", __progname, socket_name, 2617 strerror(errno)); 2618 } 2619 if (*socket_dir != '\0' && unveil(socket_dir, "c") == -1) { 2620 fatal("%s: unveil %s %s", __progname, socket_dir, 2621 strerror(errno)); 2622 } 2623 if (unveil("/", "r") == -1) 2624 fatal("%s: unveil /: %s", __progname, strerror(errno)); 2625 if ((ccp = getenv("SSH_SK_HELPER")) == NULL || *ccp == '\0') 2626 ccp = _PATH_SSH_SK_HELPER; 2627 if (unveil(ccp, "x") == -1) 2628 fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno)); 2629 if ((ccp = getenv("SSH_PKCS11_HELPER")) == NULL || *ccp == '\0') 2630 ccp = _PATH_SSH_PKCS11_HELPER; 2631 if (unveil(ccp, "x") == -1) 2632 fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno)); 2633 if ((ccp = getenv("SSH_ASKPASS")) == NULL || *ccp == '\0') 2634 ccp = _PATH_SSH_ASKPASS_DEFAULT; 2635 if (unveil(ccp, "x") == -1) 2636 fatal("%s: unveil %s: %s", __progname, ccp, strerror(errno)); 2637 if (unveil("/dev/null", "rw") == -1) 2638 fatal("%s: unveil /dev/null: %s", __progname, strerror(errno)); 2639 if (pledge("stdio rpath cpath wpath unix id proc exec", NULL) == -1) 2640 fatal("%s: pledge: %s", __progname, strerror(errno)); 2641 platform_pledge_agent(); 2642 2643 while (1) { 2644 sigprocmask(SIG_BLOCK, &nsigset, &osigset); 2645 if (signalled_exit != 0) { 2646 logit("exiting on signal %d", (int)signalled_exit); 2647 cleanup_exit((signalled_exit == SIGTERM && 2648 socket_activated) ? 0 : 2); 2649 } 2650 if (signalled_keydrop) { 2651 logit("signal %d received; removing all keys", 2652 (int)signalled_keydrop); 2653 remove_all_identities(); 2654 signalled_keydrop = 0; 2655 } 2656 ptimeout_init(&timeout); 2657 prepare_poll(&pfd, &npfd, &timeout, maxfds); 2658 result = ppoll(pfd, npfd, ptimeout_get_tsp(&timeout), &osigset); 2659 sigprocmask(SIG_SETMASK, &osigset, NULL); 2660 saved_errno = errno; 2661 if (parent_alive_interval != 0) 2662 check_parent_exists(); 2663 (void) reaper(); /* remove expired keys */ 2664 if (result == -1) { 2665 if (saved_errno == EINTR) 2666 continue; 2667 fatal("poll: %s", strerror(saved_errno)); 2668 } else if (result > 0) 2669 after_poll(pfd, npfd, maxfds); 2670 } 2671 /* NOTREACHED */ 2672 } 2673