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