1 /* $NetBSD: auth2-pubkey.c,v 1.17 2017/04/18 18:41:46 christos Exp $ */ 2 /* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */ 3 /* 4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "includes.h" 28 __RCSID("$NetBSD: auth2-pubkey.c,v 1.17 2017/04/18 18:41:46 christos Exp $"); 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <sys/wait.h> 32 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <paths.h> 36 #include <pwd.h> 37 #include <signal.h> 38 #include <stdio.h> 39 #include <stdarg.h> 40 #include <string.h> 41 #include <time.h> 42 #include <unistd.h> 43 #include <limits.h> 44 45 #include "xmalloc.h" 46 #include "ssh.h" 47 #include "ssh2.h" 48 #include "packet.h" 49 #include "buffer.h" 50 #include "log.h" 51 #include "misc.h" 52 #include "servconf.h" 53 #include "compat.h" 54 #include "key.h" 55 #include "hostfile.h" 56 #include "auth.h" 57 #include "pathnames.h" 58 #include "uidswap.h" 59 #include "auth-options.h" 60 #include "canohost.h" 61 #ifdef GSSAPI 62 #include "ssh-gss.h" 63 #endif 64 #include "monitor_wrap.h" 65 #include "authfile.h" 66 #include "match.h" 67 #include "digest.h" 68 69 #ifdef WITH_LDAP_PUBKEY 70 #include "ldapauth.h" 71 #endif 72 73 #include "ssherr.h" 74 #include "channels.h" /* XXX for session.h */ 75 #include "session.h" /* XXX for child_set_env(); refactor? */ 76 77 /* import */ 78 extern ServerOptions options; 79 extern u_char *session_id2; 80 extern u_int session_id2_len; 81 82 static int 83 userauth_pubkey(Authctxt *authctxt) 84 { 85 Buffer b; 86 Key *key = NULL; 87 char *pkalg, *userstyle, *fp = NULL; 88 u_char *pkblob, *sig; 89 u_int alen, blen, slen; 90 int have_sig, pktype; 91 int authenticated = 0; 92 93 if (!authctxt->valid) { 94 debug2("%s: disabled because of invalid user", __func__); 95 return 0; 96 } 97 have_sig = packet_get_char(); 98 if (datafellows & SSH_BUG_PKAUTH) { 99 debug2("%s: SSH_BUG_PKAUTH", __func__); 100 /* no explicit pkalg given */ 101 pkblob = packet_get_string(&blen); 102 buffer_init(&b); 103 buffer_append(&b, pkblob, blen); 104 /* so we have to extract the pkalg from the pkblob */ 105 pkalg = buffer_get_string(&b, &alen); 106 buffer_free(&b); 107 } else { 108 pkalg = packet_get_string(&alen); 109 pkblob = packet_get_string(&blen); 110 } 111 pktype = key_type_from_name(pkalg); 112 if (pktype == KEY_UNSPEC) { 113 /* this is perfectly legal */ 114 logit("%s: unsupported public key algorithm: %s", 115 __func__, pkalg); 116 goto done; 117 } 118 key = key_from_blob(pkblob, blen); 119 if (key == NULL) { 120 error("%s: cannot decode key: %s", __func__, pkalg); 121 goto done; 122 } 123 if (key->type != pktype) { 124 error("%s: type mismatch for decoded key " 125 "(received %d, expected %d)", __func__, key->type, pktype); 126 goto done; 127 } 128 if (key_type_plain(key->type) == KEY_RSA && 129 (datafellows & SSH_BUG_RSASIGMD5) != 0) { 130 logit("Refusing RSA key because client uses unsafe " 131 "signature scheme"); 132 goto done; 133 } 134 fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); 135 if (auth2_userkey_already_used(authctxt, key)) { 136 logit("refusing previously-used %s key", key_type(key)); 137 goto done; 138 } 139 if (match_pattern_list(sshkey_ssh_name(key), 140 options.pubkey_key_types, 0) != 1) { 141 logit("%s: key type %s not in PubkeyAcceptedKeyTypes", 142 __func__, sshkey_ssh_name(key)); 143 goto done; 144 } 145 146 if (have_sig) { 147 debug3("%s: have signature for %s %s", 148 __func__, sshkey_type(key), fp); 149 sig = packet_get_string(&slen); 150 packet_check_eom(); 151 buffer_init(&b); 152 if (datafellows & SSH_OLD_SESSIONID) { 153 buffer_append(&b, session_id2, session_id2_len); 154 } else { 155 buffer_put_string(&b, session_id2, session_id2_len); 156 } 157 /* reconstruct packet */ 158 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 159 xasprintf(&userstyle, "%s%s%s", authctxt->user, 160 authctxt->style ? ":" : "", 161 authctxt->style ? authctxt->style : ""); 162 buffer_put_cstring(&b, userstyle); 163 free(userstyle); 164 buffer_put_cstring(&b, 165 datafellows & SSH_BUG_PKSERVICE ? 166 "ssh-userauth" : 167 authctxt->service); 168 if (datafellows & SSH_BUG_PKAUTH) { 169 buffer_put_char(&b, have_sig); 170 } else { 171 buffer_put_cstring(&b, "publickey"); 172 buffer_put_char(&b, have_sig); 173 buffer_put_cstring(&b, pkalg); 174 } 175 buffer_put_string(&b, pkblob, blen); 176 #ifdef DEBUG_PK 177 buffer_dump(&b); 178 #endif 179 pubkey_auth_info(authctxt, key, NULL); 180 181 /* test for correct signature */ 182 authenticated = 0; 183 if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && 184 PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), 185 buffer_len(&b))) == 1) { 186 authenticated = 1; 187 /* Record the successful key to prevent reuse */ 188 auth2_record_userkey(authctxt, key); 189 key = NULL; /* Don't free below */ 190 } 191 buffer_free(&b); 192 free(sig); 193 } else { 194 debug("%s: test whether pkalg/pkblob are acceptable for %s %s", 195 __func__, sshkey_type(key), fp); 196 packet_check_eom(); 197 198 /* XXX fake reply and always send PK_OK ? */ 199 /* 200 * XXX this allows testing whether a user is allowed 201 * to login: if you happen to have a valid pubkey this 202 * message is sent. the message is NEVER sent at all 203 * if a user is not allowed to login. is this an 204 * issue? -markus 205 */ 206 if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) { 207 packet_start(SSH2_MSG_USERAUTH_PK_OK); 208 packet_put_string(pkalg, alen); 209 packet_put_string(pkblob, blen); 210 packet_send(); 211 packet_write_wait(); 212 authctxt->postponed = 1; 213 } 214 } 215 if (authenticated != 1) 216 auth_clear_options(); 217 done: 218 debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); 219 if (key != NULL) 220 key_free(key); 221 free(pkalg); 222 free(pkblob); 223 free(fp); 224 return authenticated; 225 } 226 227 void 228 pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) 229 { 230 char *fp, *extra; 231 va_list ap; 232 int i; 233 234 extra = NULL; 235 if (fmt != NULL) { 236 va_start(ap, fmt); 237 i = vasprintf(&extra, fmt, ap); 238 va_end(ap); 239 if (i < 0 || extra == NULL) 240 fatal("%s: vasprintf failed", __func__); 241 } 242 243 if (key_is_cert(key)) { 244 fp = sshkey_fingerprint(key->cert->signature_key, 245 options.fingerprint_hash, SSH_FP_DEFAULT); 246 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", 247 key_type(key), key->cert->key_id, 248 (unsigned long long)key->cert->serial, 249 key_type(key->cert->signature_key), 250 fp == NULL ? "(null)" : fp, 251 extra == NULL ? "" : ", ", extra == NULL ? "" : extra); 252 free(fp); 253 } else { 254 fp = sshkey_fingerprint(key, options.fingerprint_hash, 255 SSH_FP_DEFAULT); 256 auth_info(authctxt, "%s %s%s%s", key_type(key), 257 fp == NULL ? "(null)" : fp, 258 extra == NULL ? "" : ", ", extra == NULL ? "" : extra); 259 free(fp); 260 } 261 free(extra); 262 } 263 264 /* 265 * Splits 's' into an argument vector. Handles quoted string and basic 266 * escape characters (\\, \", \'). Caller must free the argument vector 267 * and its members. 268 */ 269 static int 270 split_argv(const char *s, int *argcp, char ***argvp) 271 { 272 int r = SSH_ERR_INTERNAL_ERROR; 273 int argc = 0, quote, i, j; 274 char *arg, **argv = xcalloc(1, sizeof(*argv)); 275 276 *argvp = NULL; 277 *argcp = 0; 278 279 for (i = 0; s[i] != '\0'; i++) { 280 /* Skip leading whitespace */ 281 if (s[i] == ' ' || s[i] == '\t') 282 continue; 283 284 /* Start of a token */ 285 quote = 0; 286 if (s[i] == '\\' && 287 (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) 288 i++; 289 else if (s[i] == '\'' || s[i] == '"') 290 quote = s[i++]; 291 292 argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); 293 arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); 294 argv[argc] = NULL; 295 296 /* Copy the token in, removing escapes */ 297 for (j = 0; s[i] != '\0'; i++) { 298 if (s[i] == '\\') { 299 if (s[i + 1] == '\'' || 300 s[i + 1] == '\"' || 301 s[i + 1] == '\\') { 302 i++; /* Skip '\' */ 303 arg[j++] = s[i]; 304 } else { 305 /* Unrecognised escape */ 306 arg[j++] = s[i]; 307 } 308 } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) 309 break; /* done */ 310 else if (quote != 0 && s[i] == quote) 311 break; /* done */ 312 else 313 arg[j++] = s[i]; 314 } 315 if (s[i] == '\0') { 316 if (quote != 0) { 317 /* Ran out of string looking for close quote */ 318 r = SSH_ERR_INVALID_FORMAT; 319 goto out; 320 } 321 break; 322 } 323 } 324 /* Success */ 325 *argcp = argc; 326 *argvp = argv; 327 argc = 0; 328 argv = NULL; 329 r = 0; 330 out: 331 if (argc != 0 && argv != NULL) { 332 for (i = 0; i < argc; i++) 333 free(argv[i]); 334 free(argv); 335 } 336 return r; 337 } 338 339 /* 340 * Reassemble an argument vector into a string, quoting and escaping as 341 * necessary. Caller must free returned string. 342 */ 343 static char * 344 assemble_argv(int argc, char **argv) 345 { 346 int i, j, ws, r; 347 char c, *ret; 348 struct sshbuf *buf, *arg; 349 350 if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) 351 fatal("%s: sshbuf_new failed", __func__); 352 353 for (i = 0; i < argc; i++) { 354 ws = 0; 355 sshbuf_reset(arg); 356 for (j = 0; argv[i][j] != '\0'; j++) { 357 r = 0; 358 c = argv[i][j]; 359 switch (c) { 360 case ' ': 361 case '\t': 362 ws = 1; 363 r = sshbuf_put_u8(arg, c); 364 break; 365 case '\\': 366 case '\'': 367 case '"': 368 if ((r = sshbuf_put_u8(arg, '\\')) != 0) 369 break; 370 /* FALLTHROUGH */ 371 default: 372 r = sshbuf_put_u8(arg, c); 373 break; 374 } 375 if (r != 0) 376 fatal("%s: sshbuf_put_u8: %s", 377 __func__, ssh_err(r)); 378 } 379 if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || 380 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || 381 (r = sshbuf_putb(buf, arg)) != 0 || 382 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) 383 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 384 } 385 if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) 386 fatal("%s: malloc failed", __func__); 387 memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); 388 ret[sshbuf_len(buf)] = '\0'; 389 sshbuf_free(buf); 390 sshbuf_free(arg); 391 return ret; 392 } 393 394 /* 395 * Runs command in a subprocess. Returns pid on success and a FILE* to the 396 * subprocess' stdout or 0 on failure. 397 * NB. "command" is only used for logging. 398 */ 399 static pid_t 400 subprocess(const char *tag, struct passwd *pw, const char *command, 401 int ac, char **av, FILE **child) 402 { 403 FILE *f; 404 struct stat st; 405 int devnull, p[2], i; 406 pid_t pid; 407 char *cp, errmsg[512]; 408 u_int envsize; 409 char **child_env; 410 411 *child = NULL; 412 413 debug3("%s: %s command \"%s\" running as %s", __func__, 414 tag, command, pw->pw_name); 415 416 /* Verify the path exists and is safe-ish to execute */ 417 if (*av[0] != '/') { 418 error("%s path is not absolute", tag); 419 return 0; 420 } 421 temporarily_use_uid(pw); 422 if (stat(av[0], &st) < 0) { 423 error("Could not stat %s \"%s\": %s", tag, 424 av[0], strerror(errno)); 425 restore_uid(); 426 return 0; 427 } 428 if (auth_secure_path(av[0], &st, NULL, 0, 429 errmsg, sizeof(errmsg)) != 0) { 430 error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); 431 restore_uid(); 432 return 0; 433 } 434 435 /* 436 * Run the command; stderr is left in place, stdout is the 437 * authorized_keys output. 438 */ 439 if (pipe(p) != 0) { 440 error("%s: pipe: %s", tag, strerror(errno)); 441 restore_uid(); 442 return 0; 443 } 444 445 /* 446 * Don't want to call this in the child, where it can fatal() and 447 * run cleanup_exit() code. 448 */ 449 restore_uid(); 450 451 switch ((pid = fork())) { 452 case -1: /* error */ 453 error("%s: fork: %s", tag, strerror(errno)); 454 close(p[0]); 455 close(p[1]); 456 return 0; 457 case 0: /* child */ 458 /* Prepare a minimal environment for the child. */ 459 envsize = 5; 460 child_env = xcalloc(sizeof(*child_env), envsize); 461 child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); 462 child_set_env(&child_env, &envsize, "USER", pw->pw_name); 463 child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); 464 child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); 465 if ((cp = getenv("LANG")) != NULL) 466 child_set_env(&child_env, &envsize, "LANG", cp); 467 468 for (i = 0; i < NSIG; i++) 469 signal(i, SIG_DFL); 470 471 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { 472 error("%s: open %s: %s", tag, _PATH_DEVNULL, 473 strerror(errno)); 474 _exit(1); 475 } 476 /* Keep stderr around a while longer to catch errors */ 477 if (dup2(devnull, STDIN_FILENO) == -1 || 478 dup2(p[1], STDOUT_FILENO) == -1) { 479 error("%s: dup2: %s", tag, strerror(errno)); 480 _exit(1); 481 } 482 if (closefrom(STDERR_FILENO + 1) == -1) { 483 error("closefrom: %s", strerror(errno)); 484 _exit(1); 485 } 486 487 /* Don't use permanently_set_uid() here to avoid fatal() */ 488 if (setgid(pw->pw_gid) == -1) { 489 error("setgid %u: %s", (u_int)pw->pw_gid, 490 strerror(errno)); 491 _exit(1); 492 } 493 if (setuid(pw->pw_uid) == -1) { 494 error("setuid %u: %s", (u_int)pw->pw_uid, 495 strerror(errno)); 496 _exit(1); 497 } 498 /* stdin is pointed to /dev/null at this point */ 499 if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { 500 error("%s: dup2: %s", tag, strerror(errno)); 501 _exit(1); 502 } 503 504 execve(av[0], av, child_env); 505 error("%s exec \"%s\": %s", tag, command, strerror(errno)); 506 _exit(127); 507 default: /* parent */ 508 break; 509 } 510 511 close(p[1]); 512 if ((f = fdopen(p[0], "r")) == NULL) { 513 error("%s: fdopen: %s", tag, strerror(errno)); 514 close(p[0]); 515 /* Don't leave zombie child */ 516 kill(pid, SIGTERM); 517 while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) 518 ; 519 return 0; 520 } 521 /* Success */ 522 debug3("%s: %s pid %ld", __func__, tag, (long)pid); 523 *child = f; 524 return pid; 525 } 526 527 /* Returns 0 if pid exited cleanly, non-zero otherwise */ 528 static int 529 exited_cleanly(pid_t pid, const char *tag, const char *cmd) 530 { 531 int status; 532 533 while (waitpid(pid, &status, 0) == -1) { 534 if (errno != EINTR) { 535 error("%s: waitpid: %s", tag, strerror(errno)); 536 return -1; 537 } 538 } 539 if (WIFSIGNALED(status)) { 540 error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); 541 return -1; 542 } else if (WEXITSTATUS(status) != 0) { 543 error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); 544 return -1; 545 } 546 return 0; 547 } 548 549 static int 550 match_principals_option(const char *principal_list, struct sshkey_cert *cert) 551 { 552 char *result; 553 u_int i; 554 555 /* XXX percent_expand() sequences for authorized_principals? */ 556 557 for (i = 0; i < cert->nprincipals; i++) { 558 if ((result = match_list(cert->principals[i], 559 principal_list, NULL)) != NULL) { 560 debug3("matched principal from key options \"%.100s\"", 561 result); 562 free(result); 563 return 1; 564 } 565 } 566 return 0; 567 } 568 569 static int 570 process_principals(FILE *f, char *file, struct passwd *pw, 571 const struct sshkey_cert *cert) 572 { 573 char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; 574 u_long linenum = 0; 575 u_int i, found_principal = 0; 576 577 while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { 578 /* Always consume entire input */ 579 if (found_principal) 580 continue; 581 /* Skip leading whitespace. */ 582 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 583 ; 584 /* Skip blank and comment lines. */ 585 if ((ep = strchr(cp, '#')) != NULL) 586 *ep = '\0'; 587 if (!*cp || *cp == '\n') 588 continue; 589 /* Trim trailing whitespace. */ 590 ep = cp + strlen(cp) - 1; 591 while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t')) 592 *ep-- = '\0'; 593 /* 594 * If the line has internal whitespace then assume it has 595 * key options. 596 */ 597 line_opts = NULL; 598 if ((ep = strrchr(cp, ' ')) != NULL || 599 (ep = strrchr(cp, '\t')) != NULL) { 600 for (; *ep == ' ' || *ep == '\t'; ep++) 601 ; 602 line_opts = cp; 603 cp = ep; 604 } 605 for (i = 0; i < cert->nprincipals; i++) { 606 if (strcmp(cp, cert->principals[i]) == 0) { 607 debug3("%s:%lu: matched principal \"%.100s\"", 608 file == NULL ? "(command)" : file, 609 linenum, cert->principals[i]); 610 if (auth_parse_options(pw, line_opts, 611 file, linenum) != 1) 612 continue; 613 found_principal = 1; 614 continue; 615 } 616 } 617 } 618 return found_principal; 619 } 620 621 static int 622 match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert) 623 { 624 FILE *f; 625 int success; 626 627 temporarily_use_uid(pw); 628 debug("trying authorized principals file %s", file); 629 if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) { 630 restore_uid(); 631 return 0; 632 } 633 success = process_principals(f, file, pw, cert); 634 fclose(f); 635 restore_uid(); 636 return success; 637 } 638 639 /* 640 * Checks whether principal is allowed in output of command. 641 * returns 1 if the principal is allowed or 0 otherwise. 642 */ 643 static int 644 match_principals_command(struct passwd *user_pw, const struct sshkey *key) 645 { 646 const struct sshkey_cert *cert = key->cert; 647 FILE *f = NULL; 648 int r, ok, found_principal = 0; 649 struct passwd *pw; 650 int i, ac = 0, uid_swapped = 0; 651 pid_t pid; 652 char *tmp, *username = NULL, *command = NULL, **av = NULL; 653 char *ca_fp = NULL, *key_fp = NULL, *catext = NULL, *keytext = NULL; 654 char serial_s[16]; 655 void (*osigchld)(int); 656 657 if (options.authorized_principals_command == NULL) 658 return 0; 659 if (options.authorized_principals_command_user == NULL) { 660 error("No user for AuthorizedPrincipalsCommand specified, " 661 "skipping"); 662 return 0; 663 } 664 665 /* 666 * NB. all returns later this function should go via "out" to 667 * ensure the original SIGCHLD handler is restored properly. 668 */ 669 osigchld = signal(SIGCHLD, SIG_DFL); 670 671 /* Prepare and verify the user for the command */ 672 username = percent_expand(options.authorized_principals_command_user, 673 "u", user_pw->pw_name, (char *)NULL); 674 pw = getpwnam(username); 675 if (pw == NULL) { 676 error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s", 677 username, strerror(errno)); 678 goto out; 679 } 680 681 /* Turn the command into an argument vector */ 682 if (split_argv(options.authorized_principals_command, &ac, &av) != 0) { 683 error("AuthorizedPrincipalsCommand \"%s\" contains " 684 "invalid quotes", command); 685 goto out; 686 } 687 if (ac == 0) { 688 error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments", 689 command); 690 goto out; 691 } 692 if ((ca_fp = sshkey_fingerprint(cert->signature_key, 693 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { 694 error("%s: sshkey_fingerprint failed", __func__); 695 goto out; 696 } 697 if ((key_fp = sshkey_fingerprint(key, 698 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { 699 error("%s: sshkey_fingerprint failed", __func__); 700 goto out; 701 } 702 if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) { 703 error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); 704 goto out; 705 } 706 if ((r = sshkey_to_base64(key, &keytext)) != 0) { 707 error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); 708 goto out; 709 } 710 snprintf(serial_s, sizeof(serial_s), "%llu", 711 (unsigned long long)cert->serial); 712 for (i = 1; i < ac; i++) { 713 tmp = percent_expand(av[i], 714 "u", user_pw->pw_name, 715 "h", user_pw->pw_dir, 716 "t", sshkey_ssh_name(key), 717 "T", sshkey_ssh_name(cert->signature_key), 718 "f", key_fp, 719 "F", ca_fp, 720 "k", keytext, 721 "K", catext, 722 "i", cert->key_id, 723 "s", serial_s, 724 (char *)NULL); 725 if (tmp == NULL) 726 fatal("%s: percent_expand failed", __func__); 727 free(av[i]); 728 av[i] = tmp; 729 } 730 /* Prepare a printable command for logs, etc. */ 731 command = assemble_argv(ac, av); 732 733 if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command, 734 ac, av, &f)) == 0) 735 goto out; 736 737 uid_swapped = 1; 738 temporarily_use_uid(pw); 739 740 ok = process_principals(f, NULL, pw, cert); 741 742 fclose(f); 743 f = NULL; 744 745 if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0) 746 goto out; 747 748 /* Read completed successfully */ 749 found_principal = ok; 750 out: 751 if (f != NULL) 752 fclose(f); 753 signal(SIGCHLD, osigchld); 754 for (i = 0; i < ac; i++) 755 free(av[i]); 756 free(av); 757 if (uid_swapped) 758 restore_uid(); 759 free(command); 760 free(username); 761 free(ca_fp); 762 free(key_fp); 763 free(catext); 764 free(keytext); 765 return found_principal; 766 } 767 /* 768 * Checks whether key is allowed in authorized_keys-format file, 769 * returns 1 if the key is allowed or 0 otherwise. 770 */ 771 static int 772 check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) 773 { 774 char line[SSH_MAX_PUBKEY_BYTES]; 775 int found_key = 0; 776 u_long linenum = 0; 777 Key *found; 778 #ifdef WITH_LDAP_PUBKEY 779 ldap_key_t * k; 780 unsigned int i = 0; 781 #endif 782 783 #ifdef WITH_LDAP_PUBKEY 784 found_key = 0; 785 /* allocate a new key type */ 786 found = key_new(key->type); 787 788 /* first check if the options is enabled, then try.. */ 789 if (options.lpk.on) { 790 debug("[LDAP] trying LDAP first uid=%s",pw->pw_name); 791 if (ldap_ismember(&options.lpk, pw->pw_name) > 0) { 792 if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) { 793 /* Skip leading whitespace, empty and comment lines. */ 794 for (i = 0 ; i < k->num ; i++) { 795 /* dont forget if multiple keys to reset options */ 796 char *cp, *xoptions = NULL; 797 798 for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++) 799 ; 800 if (!*cp || *cp == '\n' || *cp == '#') 801 continue; 802 803 if (key_read(found, &cp) != 1) { 804 /* no key? check if there are options for this key */ 805 int quoted = 0; 806 debug2("[LDAP] user_key_allowed: check options: '%s'", cp); 807 xoptions = cp; 808 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 809 if (*cp == '\\' && cp[1] == '"') 810 cp++; /* Skip both */ 811 else if (*cp == '"') 812 quoted = !quoted; 813 } 814 /* Skip remaining whitespace. */ 815 for (; *cp == ' ' || *cp == '\t'; cp++) 816 ; 817 if (key_read(found, &cp) != 1) { 818 debug2("[LDAP] user_key_allowed: advance: '%s'", cp); 819 /* still no key? advance to next line*/ 820 continue; 821 } 822 } 823 824 if (key_equal(found, key) && 825 auth_parse_options(pw, xoptions, file, linenum) == 1) { 826 found_key = 1; 827 debug("[LDAP] matching key found"); 828 char *fp = sshkey_fingerprint(found, SSH_FP_HASH_DEFAULT, SSH_FP_HEX); 829 verbose("[LDAP] Found matching %s key: %s", key_type(found), fp); 830 831 /* restoring memory */ 832 ldap_keys_free(k); 833 free(fp); 834 restore_uid(); 835 key_free(found); 836 return found_key; 837 break; 838 } 839 }/* end of LDAP for() */ 840 } else { 841 logit("[LDAP] no keys found for '%s'!", pw->pw_name); 842 } 843 } else { 844 logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup); 845 } 846 } 847 #endif 848 849 found_key = 0; 850 851 found = NULL; 852 while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { 853 char *cp, *key_options = NULL, *fp = NULL; 854 const char *reason = NULL; 855 856 /* Always consume entrire file */ 857 if (found_key) 858 continue; 859 if (found != NULL) 860 key_free(found); 861 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); 862 auth_clear_options(); 863 864 /* Skip leading whitespace, empty and comment lines. */ 865 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 866 ; 867 if (!*cp || *cp == '\n' || *cp == '#') 868 continue; 869 870 if (key_read(found, &cp) != 1) { 871 /* no key? check if there are options for this key */ 872 int quoted = 0; 873 debug2("user_key_allowed: check options: '%s'", cp); 874 key_options = cp; 875 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { 876 if (*cp == '\\' && cp[1] == '"') 877 cp++; /* Skip both */ 878 else if (*cp == '"') 879 quoted = !quoted; 880 } 881 /* Skip remaining whitespace. */ 882 for (; *cp == ' ' || *cp == '\t'; cp++) 883 ; 884 if (key_read(found, &cp) != 1) { 885 debug2("user_key_allowed: advance: '%s'", cp); 886 /* still no key? advance to next line*/ 887 continue; 888 } 889 } 890 if (key_is_cert(key)) { 891 if (!key_equal(found, key->cert->signature_key)) 892 continue; 893 if (auth_parse_options(pw, key_options, file, 894 linenum) != 1) 895 continue; 896 if (!key_is_cert_authority) 897 continue; 898 if ((fp = sshkey_fingerprint(found, 899 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 900 continue; 901 debug("matching CA found: file %s, line %lu, %s %s", 902 file, linenum, key_type(found), fp); 903 /* 904 * If the user has specified a list of principals as 905 * a key option, then prefer that list to matching 906 * their username in the certificate principals list. 907 */ 908 if (authorized_principals != NULL && 909 !match_principals_option(authorized_principals, 910 key->cert)) { 911 reason = "Certificate does not contain an " 912 "authorized principal"; 913 fail_reason: 914 free(fp); 915 error("%s", reason); 916 auth_debug_add("%s", reason); 917 continue; 918 } 919 if (key_cert_check_authority(key, 0, 0, 920 authorized_principals == NULL ? pw->pw_name : NULL, 921 &reason) != 0) 922 goto fail_reason; 923 if (auth_cert_options(key, pw, &reason) != 0) 924 goto fail_reason; 925 verbose("Accepted certificate ID \"%s\" (serial %llu) " 926 "signed by %s CA %s via %s", key->cert->key_id, 927 (unsigned long long)key->cert->serial, 928 key_type(found), fp, file); 929 free(fp); 930 found_key = 1; 931 break; 932 } else if (key_equal(found, key)) { 933 if (auth_parse_options(pw, key_options, file, 934 linenum) != 1) 935 continue; 936 if (key_is_cert_authority) 937 continue; 938 if ((fp = sshkey_fingerprint(found, 939 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 940 continue; 941 debug("matching key found: file %s, line %lu %s %s", 942 file, linenum, key_type(found), fp); 943 free(fp); 944 found_key = 1; 945 continue; 946 } 947 } 948 if (found != NULL) 949 key_free(found); 950 if (!found_key) 951 debug2("key not found"); 952 return found_key; 953 } 954 955 /* Authenticate a certificate key against TrustedUserCAKeys */ 956 static int 957 user_cert_trusted_ca(struct passwd *pw, Key *key) 958 { 959 char *ca_fp, *principals_file = NULL; 960 const char *reason; 961 int ret = 0, found_principal = 0, use_authorized_principals; 962 963 if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) 964 return 0; 965 966 if ((ca_fp = sshkey_fingerprint(key->cert->signature_key, 967 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 968 return 0; 969 970 if (sshkey_in_file(key->cert->signature_key, 971 options.trusted_user_ca_keys, 1, 0) != 0) { 972 debug2("%s: CA %s %s is not listed in %s", __func__, 973 key_type(key->cert->signature_key), ca_fp, 974 options.trusted_user_ca_keys); 975 goto out; 976 } 977 /* 978 * If AuthorizedPrincipals is in use, then compare the certificate 979 * principals against the names in that file rather than matching 980 * against the username. 981 */ 982 if ((principals_file = authorized_principals_file(pw)) != NULL) { 983 if (match_principals_file(principals_file, pw, key->cert)) 984 found_principal = 1; 985 } 986 /* Try querying command if specified */ 987 if (!found_principal && match_principals_command(pw, key)) 988 found_principal = 1; 989 /* If principals file or command is specified, then require a match */ 990 use_authorized_principals = principals_file != NULL || 991 options.authorized_principals_command != NULL; 992 if (!found_principal && use_authorized_principals) { 993 reason = "Certificate does not contain an authorized principal"; 994 fail_reason: 995 error("%s", reason); 996 auth_debug_add("%s", reason); 997 goto out; 998 } 999 if (key_cert_check_authority(key, 0, 1, 1000 use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) 1001 goto fail_reason; 1002 if (auth_cert_options(key, pw, &reason) != 0) 1003 goto fail_reason; 1004 1005 verbose("Accepted certificate ID \"%s\" (serial %llu) signed by " 1006 "%s CA %s via %s", key->cert->key_id, 1007 (unsigned long long)key->cert->serial, 1008 key_type(key->cert->signature_key), ca_fp, 1009 options.trusted_user_ca_keys); 1010 ret = 1; 1011 1012 out: 1013 free(principals_file); 1014 free(ca_fp); 1015 return ret; 1016 } 1017 1018 /* 1019 * Checks whether key is allowed in file. 1020 * returns 1 if the key is allowed or 0 otherwise. 1021 */ 1022 static int 1023 user_key_allowed2(struct passwd *pw, Key *key, char *file) 1024 { 1025 FILE *f; 1026 int found_key = 0; 1027 1028 /* Temporarily use the user's uid. */ 1029 temporarily_use_uid(pw); 1030 1031 debug("trying public key file %s", file); 1032 if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) { 1033 found_key = check_authkeys_file(f, file, key, pw); 1034 fclose(f); 1035 } 1036 1037 restore_uid(); 1038 return found_key; 1039 } 1040 1041 /* 1042 * Checks whether key is allowed in output of command. 1043 * returns 1 if the key is allowed or 0 otherwise. 1044 */ 1045 static int 1046 user_key_command_allowed2(struct passwd *user_pw, Key *key) 1047 { 1048 FILE *f = NULL; 1049 int r, ok, found_key = 0; 1050 struct passwd *pw; 1051 int i, uid_swapped = 0, ac = 0; 1052 pid_t pid; 1053 char *username = NULL, *key_fp = NULL, *keytext = NULL; 1054 char *tmp, *command = NULL, **av = NULL; 1055 void (*osigchld)(int); 1056 1057 if (options.authorized_keys_command == NULL) 1058 return 0; 1059 if (options.authorized_keys_command_user == NULL) { 1060 error("No user for AuthorizedKeysCommand specified, skipping"); 1061 return 0; 1062 } 1063 1064 /* 1065 * NB. all returns later this function should go via "out" to 1066 * ensure the original SIGCHLD handler is restored properly. 1067 */ 1068 osigchld = signal(SIGCHLD, SIG_DFL); 1069 1070 /* Prepare and verify the user for the command */ 1071 username = percent_expand(options.authorized_keys_command_user, 1072 "u", user_pw->pw_name, (char *)NULL); 1073 pw = getpwnam(username); 1074 if (pw == NULL) { 1075 error("AuthorizedKeysCommandUser \"%s\" not found: %s", 1076 username, strerror(errno)); 1077 goto out; 1078 } 1079 1080 /* Prepare AuthorizedKeysCommand */ 1081 if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, 1082 SSH_FP_DEFAULT)) == NULL) { 1083 error("%s: sshkey_fingerprint failed", __func__); 1084 goto out; 1085 } 1086 if ((r = sshkey_to_base64(key, &keytext)) != 0) { 1087 error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); 1088 goto out; 1089 } 1090 1091 /* Turn the command into an argument vector */ 1092 if (split_argv(options.authorized_keys_command, &ac, &av) != 0) { 1093 error("AuthorizedKeysCommand \"%s\" contains invalid quotes", 1094 command); 1095 goto out; 1096 } 1097 if (ac == 0) { 1098 error("AuthorizedKeysCommand \"%s\" yielded no arguments", 1099 command); 1100 goto out; 1101 } 1102 for (i = 1; i < ac; i++) { 1103 tmp = percent_expand(av[i], 1104 "u", user_pw->pw_name, 1105 "h", user_pw->pw_dir, 1106 "t", sshkey_ssh_name(key), 1107 "f", key_fp, 1108 "k", keytext, 1109 (char *)NULL); 1110 if (tmp == NULL) 1111 fatal("%s: percent_expand failed", __func__); 1112 free(av[i]); 1113 av[i] = tmp; 1114 } 1115 /* Prepare a printable command for logs, etc. */ 1116 command = assemble_argv(ac, av); 1117 1118 /* 1119 * If AuthorizedKeysCommand was run without arguments 1120 * then fall back to the old behaviour of passing the 1121 * target username as a single argument. 1122 */ 1123 if (ac == 1) { 1124 av = xreallocarray(av, ac + 2, sizeof(*av)); 1125 av[1] = xstrdup(user_pw->pw_name); 1126 av[2] = NULL; 1127 /* Fix up command too, since it is used in log messages */ 1128 free(command); 1129 xasprintf(&command, "%s %s", av[0], av[1]); 1130 } 1131 1132 if ((pid = subprocess("AuthorizedKeysCommand", pw, command, 1133 ac, av, &f)) == 0) 1134 goto out; 1135 1136 uid_swapped = 1; 1137 temporarily_use_uid(pw); 1138 1139 ok = check_authkeys_file(f, options.authorized_keys_command, key, pw); 1140 1141 fclose(f); 1142 f = NULL; 1143 1144 if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0) 1145 goto out; 1146 1147 /* Read completed successfully */ 1148 found_key = ok; 1149 out: 1150 if (f != NULL) 1151 fclose(f); 1152 signal(SIGCHLD, osigchld); 1153 for (i = 0; i < ac; i++) 1154 free(av[i]); 1155 free(av); 1156 if (uid_swapped) 1157 restore_uid(); 1158 free(command); 1159 free(username); 1160 free(key_fp); 1161 free(keytext); 1162 return found_key; 1163 } 1164 1165 /* 1166 * Check whether key authenticates and authorises the user. 1167 */ 1168 int 1169 user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) 1170 { 1171 u_int success, i; 1172 char *file; 1173 1174 if (auth_key_is_revoked(key)) 1175 return 0; 1176 if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) 1177 return 0; 1178 1179 success = user_cert_trusted_ca(pw, key); 1180 if (success) 1181 return success; 1182 1183 success = user_key_command_allowed2(pw, key); 1184 if (success > 0) 1185 return success; 1186 1187 for (i = 0; !success && i < options.num_authkeys_files; i++) { 1188 1189 if (strcasecmp(options.authorized_keys_files[i], "none") == 0) 1190 continue; 1191 file = expand_authorized_keys( 1192 options.authorized_keys_files[i], pw); 1193 1194 success = user_key_allowed2(pw, key, file); 1195 free(file); 1196 } 1197 1198 return success; 1199 } 1200 1201 /* Records a public key in the list of previously-successful keys */ 1202 void 1203 auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) 1204 { 1205 struct sshkey **tmp; 1206 1207 if (authctxt->nprev_userkeys >= INT_MAX || 1208 (tmp = reallocarray(authctxt->prev_userkeys, 1209 authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) 1210 fatal("%s: reallocarray failed", __func__); 1211 authctxt->prev_userkeys = tmp; 1212 authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; 1213 authctxt->nprev_userkeys++; 1214 } 1215 1216 /* Checks whether a key has already been used successfully for authentication */ 1217 int 1218 auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) 1219 { 1220 u_int i; 1221 1222 for (i = 0; i < authctxt->nprev_userkeys; i++) { 1223 if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { 1224 return 1; 1225 } 1226 } 1227 return 0; 1228 } 1229 1230 Authmethod method_pubkey = { 1231 "publickey", 1232 userauth_pubkey, 1233 &options.pubkey_authentication 1234 }; 1235