summaryrefslogtreecommitdiff
path: root/auth2-pubkey.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2013-05-07 10:06:42 +0100
committerColin Watson <cjwatson@debian.org>2013-05-07 10:06:42 +0100
commitecebda56da46a03dafff923d91c382f31faa9eec (patch)
tree449614b6c06a2622c74a609b31fcc46c60037c56 /auth2-pubkey.c
parentc6a2c0334e45419875687d250aed9bea78480f2e (diff)
parentffc06452028ba78cd693d4ed43df8b60a10d6163 (diff)
merge 6.2p1; reorder additions to monitor.h for easier merging in future
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r--auth2-pubkey.c216
1 files changed, 196 insertions, 20 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 5bccb5d76..3ff6faa8b 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.30 2011/09/25 05:44:47 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.34 2013/02/14 21:35:59 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -27,9 +27,15 @@
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <sys/wait.h>
30 31
32#include <errno.h>
31#include <fcntl.h> 33#include <fcntl.h>
34#ifdef HAVE_PATHS_H
35# include <paths.h>
36#endif
32#include <pwd.h> 37#include <pwd.h>
38#include <signal.h>
33#include <stdio.h> 39#include <stdio.h>
34#include <stdarg.h> 40#include <stdarg.h>
35#include <string.h> 41#include <string.h>
@@ -240,7 +246,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
240 if (strcmp(cp, cert->principals[i]) == 0) { 246 if (strcmp(cp, cert->principals[i]) == 0) {
241 debug3("matched principal \"%.100s\" " 247 debug3("matched principal \"%.100s\" "
242 "from file \"%s\" on line %lu", 248 "from file \"%s\" on line %lu",
243 cert->principals[i], file, linenum); 249 cert->principals[i], file, linenum);
244 if (auth_parse_options(pw, line_opts, 250 if (auth_parse_options(pw, line_opts,
245 file, linenum) != 1) 251 file, linenum) != 1)
246 continue; 252 continue;
@@ -253,31 +259,22 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
253 fclose(f); 259 fclose(f);
254 restore_uid(); 260 restore_uid();
255 return 0; 261 return 0;
256} 262}
257 263
258/* return 1 if user allows given key */ 264/*
265 * Checks whether key is allowed in authorized_keys-format file,
266 * returns 1 if the key is allowed or 0 otherwise.
267 */
259static int 268static int
260user_key_allowed2(struct passwd *pw, Key *key, char *file) 269check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
261{ 270{
262 char line[SSH_MAX_PUBKEY_BYTES]; 271 char line[SSH_MAX_PUBKEY_BYTES];
263 const char *reason; 272 const char *reason;
264 int found_key = 0; 273 int found_key = 0;
265 FILE *f;
266 u_long linenum = 0; 274 u_long linenum = 0;
267 Key *found; 275 Key *found;
268 char *fp; 276 char *fp;
269 277
270 /* Temporarily use the user's uid. */
271 temporarily_use_uid(pw);
272
273 debug("trying public key file %s", file);
274 f = auth_openkeyfile(file, pw, options.strict_modes);
275
276 if (!f) {
277 restore_uid();
278 return 0;
279 }
280
281 found_key = 0; 278 found_key = 0;
282 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); 279 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
283 280
@@ -370,8 +367,6 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
370 break; 367 break;
371 } 368 }
372 } 369 }
373 restore_uid();
374 fclose(f);
375 key_free(found); 370 key_free(found);
376 if (!found_key) 371 if (!found_key)
377 debug2("key not found"); 372 debug2("key not found");
@@ -433,7 +428,180 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
433 return ret; 428 return ret;
434} 429}
435 430
436/* check whether given key is in .ssh/authorized_keys* */ 431/*
432 * Checks whether key is allowed in file.
433 * returns 1 if the key is allowed or 0 otherwise.
434 */
435static int
436user_key_allowed2(struct passwd *pw, Key *key, char *file)
437{
438 FILE *f;
439 int found_key = 0;
440
441 /* Temporarily use the user's uid. */
442 temporarily_use_uid(pw);
443
444 debug("trying public key file %s", file);
445 if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
446 found_key = check_authkeys_file(f, file, key, pw);
447 fclose(f);
448 }
449
450 restore_uid();
451 return found_key;
452}
453
454/*
455 * Checks whether key is allowed in output of command.
456 * returns 1 if the key is allowed or 0 otherwise.
457 */
458static int
459user_key_command_allowed2(struct passwd *user_pw, Key *key)
460{
461 FILE *f;
462 int ok, found_key = 0;
463 struct passwd *pw;
464 struct stat st;
465 int status, devnull, p[2], i;
466 pid_t pid;
467 char *username, errmsg[512];
468
469 if (options.authorized_keys_command == NULL ||
470 options.authorized_keys_command[0] != '/')
471 return 0;
472
473 if (options.authorized_keys_command_user == NULL) {
474 error("No user for AuthorizedKeysCommand specified, skipping");
475 return 0;
476 }
477
478 username = percent_expand(options.authorized_keys_command_user,
479 "u", user_pw->pw_name, (char *)NULL);
480 pw = getpwnam(username);
481 if (pw == NULL) {
482 error("AuthorizedKeysCommandUser \"%s\" not found: %s",
483 username, strerror(errno));
484 free(username);
485 return 0;
486 }
487 free(username);
488
489 temporarily_use_uid(pw);
490
491 if (stat(options.authorized_keys_command, &st) < 0) {
492 error("Could not stat AuthorizedKeysCommand \"%s\": %s",
493 options.authorized_keys_command, strerror(errno));
494 goto out;
495 }
496 if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
497 errmsg, sizeof(errmsg)) != 0) {
498 error("Unsafe AuthorizedKeysCommand: %s", errmsg);
499 goto out;
500 }
501
502 if (pipe(p) != 0) {
503 error("%s: pipe: %s", __func__, strerror(errno));
504 goto out;
505 }
506
507 debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
508 options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
509
510 /*
511 * Don't want to call this in the child, where it can fatal() and
512 * run cleanup_exit() code.
513 */
514 restore_uid();
515
516 switch ((pid = fork())) {
517 case -1: /* error */
518 error("%s: fork: %s", __func__, strerror(errno));
519 close(p[0]);
520 close(p[1]);
521 return 0;
522 case 0: /* child */
523 for (i = 0; i < NSIG; i++)
524 signal(i, SIG_DFL);
525
526 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
527 error("%s: open %s: %s", __func__, _PATH_DEVNULL,
528 strerror(errno));
529 _exit(1);
530 }
531 /* Keep stderr around a while longer to catch errors */
532 if (dup2(devnull, STDIN_FILENO) == -1 ||
533 dup2(p[1], STDOUT_FILENO) == -1) {
534 error("%s: dup2: %s", __func__, strerror(errno));
535 _exit(1);
536 }
537 closefrom(STDERR_FILENO + 1);
538
539 /* Don't use permanently_set_uid() here to avoid fatal() */
540 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
541 error("setresgid %u: %s", (u_int)pw->pw_gid,
542 strerror(errno));
543 _exit(1);
544 }
545 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
546 error("setresuid %u: %s", (u_int)pw->pw_uid,
547 strerror(errno));
548 _exit(1);
549 }
550 /* stdin is pointed to /dev/null at this point */
551 if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
552 error("%s: dup2: %s", __func__, strerror(errno));
553 _exit(1);
554 }
555
556 execl(options.authorized_keys_command,
557 options.authorized_keys_command, user_pw->pw_name, NULL);
558
559 error("AuthorizedKeysCommand %s exec failed: %s",
560 options.authorized_keys_command, strerror(errno));
561 _exit(127);
562 default: /* parent */
563 break;
564 }
565
566 temporarily_use_uid(pw);
567
568 close(p[1]);
569 if ((f = fdopen(p[0], "r")) == NULL) {
570 error("%s: fdopen: %s", __func__, strerror(errno));
571 close(p[0]);
572 /* Don't leave zombie child */
573 kill(pid, SIGTERM);
574 while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
575 ;
576 goto out;
577 }
578 ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
579 fclose(f);
580
581 while (waitpid(pid, &status, 0) == -1) {
582 if (errno != EINTR) {
583 error("%s: waitpid: %s", __func__, strerror(errno));
584 goto out;
585 }
586 }
587 if (WIFSIGNALED(status)) {
588 error("AuthorizedKeysCommand %s exited on signal %d",
589 options.authorized_keys_command, WTERMSIG(status));
590 goto out;
591 } else if (WEXITSTATUS(status) != 0) {
592 error("AuthorizedKeysCommand %s returned status %d",
593 options.authorized_keys_command, WEXITSTATUS(status));
594 goto out;
595 }
596 found_key = ok;
597 out:
598 restore_uid();
599 return found_key;
600}
601
602/*
603 * Check whether key authenticates and authorises the user.
604 */
437int 605int
438user_key_allowed(struct passwd *pw, Key *key) 606user_key_allowed(struct passwd *pw, Key *key)
439{ 607{
@@ -449,9 +617,17 @@ user_key_allowed(struct passwd *pw, Key *key)
449 if (success) 617 if (success)
450 return success; 618 return success;
451 619
620 success = user_key_command_allowed2(pw, key);
621 if (success > 0)
622 return success;
623
452 for (i = 0; !success && i < options.num_authkeys_files; i++) { 624 for (i = 0; !success && i < options.num_authkeys_files; i++) {
625
626 if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
627 continue;
453 file = expand_authorized_keys( 628 file = expand_authorized_keys(
454 options.authorized_keys_files[i], pw); 629 options.authorized_keys_files[i], pw);
630
455 success = user_key_allowed2(pw, key, file); 631 success = user_key_allowed2(pw, key, file);
456 xfree(file); 632 xfree(file);
457 } 633 }