|
Lines 26-34
Link Here
|
| 26 |
|
26 |
|
| 27 |
#include <sys/types.h> |
27 |
#include <sys/types.h> |
| 28 |
#include <sys/stat.h> |
28 |
#include <sys/stat.h> |
|
|
29 |
#include <sys/wait.h> |
| 29 |
|
30 |
|
|
|
31 |
#include <errno.h> |
| 30 |
#include <fcntl.h> |
32 |
#include <fcntl.h> |
|
|
33 |
#include <paths.h> |
| 31 |
#include <pwd.h> |
34 |
#include <pwd.h> |
|
|
35 |
#include <signal.h> |
| 32 |
#include <stdio.h> |
36 |
#include <stdio.h> |
| 33 |
#include <stdarg.h> |
37 |
#include <stdarg.h> |
| 34 |
#include <string.h> |
38 |
#include <string.h> |
|
Lines 239-245
match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
Link Here
|
| 239 |
if (strcmp(cp, cert->principals[i]) == 0) { |
243 |
if (strcmp(cp, cert->principals[i]) == 0) { |
| 240 |
debug3("matched principal \"%.100s\" " |
244 |
debug3("matched principal \"%.100s\" " |
| 241 |
"from file \"%s\" on line %lu", |
245 |
"from file \"%s\" on line %lu", |
| 242 |
cert->principals[i], file, linenum); |
246 |
cert->principals[i], file, linenum); |
| 243 |
if (auth_parse_options(pw, line_opts, |
247 |
if (auth_parse_options(pw, line_opts, |
| 244 |
file, linenum) != 1) |
248 |
file, linenum) != 1) |
| 245 |
continue; |
249 |
continue; |
|
Lines 252-282
match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
Link Here
|
| 252 |
fclose(f); |
256 |
fclose(f); |
| 253 |
restore_uid(); |
257 |
restore_uid(); |
| 254 |
return 0; |
258 |
return 0; |
| 255 |
} |
259 |
} |
| 256 |
|
260 |
|
| 257 |
/* return 1 if user allows given key */ |
261 |
/* |
|
|
262 |
* Checks whether key is allowed in authorized_keys-format file, |
| 263 |
* returns 1 if the key is allowed or 0 otherwise. |
| 264 |
*/ |
| 258 |
static int |
265 |
static int |
| 259 |
user_key_allowed2(struct passwd *pw, Key *key, char *file) |
266 |
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) |
| 260 |
{ |
267 |
{ |
| 261 |
char line[SSH_MAX_PUBKEY_BYTES]; |
268 |
char line[SSH_MAX_PUBKEY_BYTES]; |
| 262 |
const char *reason; |
269 |
const char *reason; |
| 263 |
int found_key = 0; |
270 |
int found_key = 0; |
| 264 |
FILE *f; |
|
|
| 265 |
u_long linenum = 0; |
271 |
u_long linenum = 0; |
| 266 |
Key *found; |
272 |
Key *found; |
| 267 |
char *fp; |
273 |
char *fp; |
| 268 |
|
274 |
|
| 269 |
/* Temporarily use the user's uid. */ |
|
|
| 270 |
temporarily_use_uid(pw); |
| 271 |
|
| 272 |
debug("trying public key file %s", file); |
| 273 |
f = auth_openkeyfile(file, pw, options.strict_modes); |
| 274 |
|
| 275 |
if (!f) { |
| 276 |
restore_uid(); |
| 277 |
return 0; |
| 278 |
} |
| 279 |
|
| 280 |
found_key = 0; |
275 |
found_key = 0; |
| 281 |
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); |
276 |
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); |
| 282 |
|
277 |
|
|
Lines 369-376
user_key_allowed2(struct passwd *pw, Key *key, char *file)
Link Here
|
| 369 |
break; |
364 |
break; |
| 370 |
} |
365 |
} |
| 371 |
} |
366 |
} |
| 372 |
restore_uid(); |
|
|
| 373 |
fclose(f); |
| 374 |
key_free(found); |
367 |
key_free(found); |
| 375 |
if (!found_key) |
368 |
if (!found_key) |
| 376 |
debug2("key not found"); |
369 |
debug2("key not found"); |
|
Lines 432-438
user_cert_trusted_ca(struct passwd *pw, Key *key)
Link Here
|
| 432 |
return ret; |
425 |
return ret; |
| 433 |
} |
426 |
} |
| 434 |
|
427 |
|
| 435 |
/* check whether given key is in .ssh/authorized_keys* */ |
428 |
/* |
|
|
429 |
* Checks whether key is allowed in file. |
| 430 |
* returns 1 if the key is allowed or 0 otherwise. |
| 431 |
*/ |
| 432 |
static int |
| 433 |
user_key_allowed2(struct passwd *pw, Key *key, char *file) |
| 434 |
{ |
| 435 |
FILE *f; |
| 436 |
int found_key = 0; |
| 437 |
|
| 438 |
/* Temporarily use the user's uid. */ |
| 439 |
temporarily_use_uid(pw); |
| 440 |
|
| 441 |
debug("trying public key file %s", file); |
| 442 |
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) { |
| 443 |
found_key = check_authkeys_file(f, file, key, pw); |
| 444 |
fclose(f); |
| 445 |
} |
| 446 |
|
| 447 |
restore_uid(); |
| 448 |
return found_key; |
| 449 |
} |
| 450 |
|
| 451 |
/* |
| 452 |
* Checks whether key is allowed in output of command. |
| 453 |
* returns 1 if the key is allowed or 0 otherwise. |
| 454 |
*/ |
| 455 |
static int |
| 456 |
user_key_command_allowed2(struct passwd *user_pw, Key *key) |
| 457 |
{ |
| 458 |
FILE *f; |
| 459 |
int ok, found_key = 0; |
| 460 |
struct passwd *pw; |
| 461 |
struct stat st; |
| 462 |
int status, devnull, p[2], i; |
| 463 |
pid_t pid; |
| 464 |
char errmsg[512]; |
| 465 |
|
| 466 |
if (options.authorized_keys_command == NULL || |
| 467 |
options.authorized_keys_command[0] != '/') |
| 468 |
return 0; |
| 469 |
|
| 470 |
/* If no user specified to run commands the default to target user */ |
| 471 |
if (options.authorized_keys_command_user == NULL) |
| 472 |
pw = user_pw; |
| 473 |
else { |
| 474 |
pw = getpwnam(options.authorized_keys_command_user); |
| 475 |
if (pw == NULL) { |
| 476 |
error("AuthorizedKeyCommandUser \"%s\" not found: %s", |
| 477 |
options.authorized_keys_command, strerror(errno)); |
| 478 |
return 0; |
| 479 |
} |
| 480 |
} |
| 481 |
|
| 482 |
temporarily_use_uid(pw); |
| 483 |
|
| 484 |
if (stat(options.authorized_keys_command, &st) < 0) { |
| 485 |
error("Could not stat AuthorizedKeysCommand \"%s\": %s", |
| 486 |
options.authorized_keys_command, strerror(errno)); |
| 487 |
goto out; |
| 488 |
} |
| 489 |
if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0, |
| 490 |
errmsg, sizeof(errmsg)) != 0) { |
| 491 |
error("Unsafe AuthorizedKeysCommand: %s", errmsg); |
| 492 |
goto out; |
| 493 |
} |
| 494 |
|
| 495 |
/* open the pipe and read the keys */ |
| 496 |
if (pipe(p) != 0) { |
| 497 |
error("%s: pipe: %s", __func__, strerror(errno)); |
| 498 |
goto out; |
| 499 |
} |
| 500 |
|
| 501 |
debug3("Running AuthorizedKeysCommand: \"%s\" as \"%s\"", |
| 502 |
options.authorized_keys_command, pw->pw_name); |
| 503 |
|
| 504 |
/* |
| 505 |
* Don't want to call this in the child, where it can fatal() and |
| 506 |
* run cleanup_exit() code. |
| 507 |
*/ |
| 508 |
restore_uid(); |
| 509 |
|
| 510 |
switch ((pid = fork())) { |
| 511 |
case -1: /* error */ |
| 512 |
error("%s: fork: %s", __func__, strerror(errno)); |
| 513 |
close(p[0]); |
| 514 |
close(p[1]); |
| 515 |
return 0; |
| 516 |
case 0: /* child */ |
| 517 |
for (i = 0; i < NSIG; i++) |
| 518 |
signal(i, SIG_DFL); |
| 519 |
|
| 520 |
/* Don't use permanently_set_uid() here to avoid fatal() */ |
| 521 |
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { |
| 522 |
error("setresgid %u: %s", (u_int)pw->pw_gid, |
| 523 |
strerror(errno)); |
| 524 |
_exit(1); |
| 525 |
} |
| 526 |
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { |
| 527 |
error("setresuid %u: %s", (u_int)pw->pw_uid, |
| 528 |
strerror(errno)); |
| 529 |
_exit(1); |
| 530 |
} |
| 531 |
|
| 532 |
close(p[0]); |
| 533 |
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { |
| 534 |
error("%s: open %s: %s", __func__, _PATH_DEVNULL, |
| 535 |
strerror(errno)); |
| 536 |
_exit(1); |
| 537 |
} |
| 538 |
if (dup2(devnull, STDIN_FILENO) == -1 || |
| 539 |
dup2(p[1], STDOUT_FILENO) == -1 || |
| 540 |
dup2(devnull, STDERR_FILENO) == -1) { |
| 541 |
error("%s: dup2: %s", __func__, strerror(errno)); |
| 542 |
_exit(1); |
| 543 |
} |
| 544 |
closefrom(STDERR_FILENO + 1); |
| 545 |
|
| 546 |
execl(options.authorized_keys_command, |
| 547 |
options.authorized_keys_command, pw->pw_name, NULL); |
| 548 |
|
| 549 |
error("AuthorizedKeysCommand %s exec failed: %s", |
| 550 |
options.authorized_keys_command, strerror(errno)); |
| 551 |
_exit(127); |
| 552 |
default: /* parent */ |
| 553 |
break; |
| 554 |
} |
| 555 |
|
| 556 |
temporarily_use_uid(pw); |
| 557 |
|
| 558 |
close(p[1]); |
| 559 |
if ((f = fdopen(p[0], "r")) == NULL) { |
| 560 |
error("%s: fdopen: %s", __func__, strerror(errno)); |
| 561 |
close(p[0]); |
| 562 |
/* Don't leave zombie child */ |
| 563 |
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) |
| 564 |
; |
| 565 |
goto out; |
| 566 |
} |
| 567 |
ok = check_authkeys_file(f, options.authorized_keys_command, key, pw); |
| 568 |
fclose(f); |
| 569 |
|
| 570 |
while (waitpid(pid, &status, 0) == -1) { |
| 571 |
if (errno != EINTR) { |
| 572 |
error("%s: waitpid: %s", __func__, strerror(errno)); |
| 573 |
goto out; |
| 574 |
} |
| 575 |
} |
| 576 |
if (WIFSIGNALED(status)) { |
| 577 |
error("AuthorizedKeysCommand %s exited on signal %d", |
| 578 |
options.authorized_keys_command, WTERMSIG(status)); |
| 579 |
goto out; |
| 580 |
} else if (WEXITSTATUS(status) != 0) { |
| 581 |
error("AuthorizedKeysCommand %s returned status %d", |
| 582 |
options.authorized_keys_command, WEXITSTATUS(status)); |
| 583 |
goto out; |
| 584 |
} |
| 585 |
found_key = ok; |
| 586 |
out: |
| 587 |
restore_uid(); |
| 588 |
return found_key; |
| 589 |
} |
| 590 |
|
| 591 |
/* |
| 592 |
* Check whether key authenticates and authorises the user. |
| 593 |
*/ |
| 436 |
int |
594 |
int |
| 437 |
user_key_allowed(struct passwd *pw, Key *key) |
595 |
user_key_allowed(struct passwd *pw, Key *key) |
| 438 |
{ |
596 |
{ |
|
Lines 448-453
user_key_allowed(struct passwd *pw, Key *key)
Link Here
|
| 448 |
if (success) |
606 |
if (success) |
| 449 |
return success; |
607 |
return success; |
| 450 |
|
608 |
|
|
|
609 |
success = user_key_command_allowed2(pw, key); |
| 610 |
if (success > 0) |
| 611 |
return success; |
| 612 |
|
| 451 |
for (i = 0; !success && i < options.num_authkeys_files; i++) { |
613 |
for (i = 0; !success && i < options.num_authkeys_files; i++) { |
| 452 |
file = expand_authorized_keys( |
614 |
file = expand_authorized_keys( |
| 453 |
options.authorized_keys_files[i], pw); |
615 |
options.authorized_keys_files[i], pw); |