diff options
author | Colin Watson <cjwatson@debian.org> | 2010-03-31 10:46:28 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2010-03-31 10:46:28 +0100 |
commit | efd3d4522636ae029488c2e9730b60c88e257d2e (patch) | |
tree | 31e02ac3f16090ce8c53448677356b2b7f423683 /auth.c | |
parent | bbec4db36d464ea1d464a707625125f9fd5c7b5e (diff) | |
parent | d1a87e462e1db89f19cd960588d0c6b287cb5ccc (diff) |
* New upstream release (LP: #535029).
- After a transition period of about 10 years, this release disables SSH
protocol 1 by default. Clients and servers that need to use the
legacy protocol must explicitly enable it in ssh_config / sshd_config
or on the command-line.
- Remove the libsectok/OpenSC-based smartcard code and add support for
PKCS#11 tokens. This support is enabled by default in the Debian
packaging, since it now doesn't involve additional library
dependencies (closes: #231472, LP: #16918).
- Add support for certificate authentication of users and hosts using a
new, minimal OpenSSH certificate format (closes: #482806).
- Added a 'netcat mode' to ssh(1): "ssh -W host:port ...".
- Add the ability to revoke keys in sshd(8) and ssh(1). (For the Debian
package, this overlaps with the key blacklisting facility added in
openssh 1:4.7p1-9, but with different file formats and slightly
different scopes; for the moment, I've roughly merged the two.)
- Various multiplexing improvements, including support for requesting
port-forwardings via the multiplex protocol (closes: #360151).
- Allow setting an explicit umask on the sftp-server(8) commandline to
override whatever default the user has (closes: #496843).
- Many sftp client improvements, including tab-completion, more options,
and recursive transfer support for get/put (LP: #33378). The old
mget/mput commands never worked properly and have been removed
(closes: #270399, #428082).
- Do not prompt for a passphrase if we fail to open a keyfile, and log
the reason why the open failed to debug (closes: #431538).
- Prevent sftp from crashing when given a "-" without a command. Also,
allow whitespace to follow a "-" (closes: #531561).
Diffstat (limited to 'auth.c')
-rw-r--r-- | auth.c | 148 |
1 files changed, 98 insertions, 50 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.80 2008/11/04 07:58:09 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.86 2010/03/05 02:58:11 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -70,6 +70,7 @@ | |||
70 | #ifdef GSSAPI | 70 | #ifdef GSSAPI |
71 | #include "ssh-gss.h" | 71 | #include "ssh-gss.h" |
72 | #endif | 72 | #endif |
73 | #include "authfile.h" | ||
73 | #include "monitor_wrap.h" | 74 | #include "monitor_wrap.h" |
74 | 75 | ||
75 | /* import */ | 76 | /* import */ |
@@ -96,7 +97,6 @@ allowed_user(struct passwd * pw) | |||
96 | { | 97 | { |
97 | struct stat st; | 98 | struct stat st; |
98 | const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; | 99 | const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; |
99 | char *shell; | ||
100 | u_int i; | 100 | u_int i; |
101 | #ifdef USE_SHADOW | 101 | #ifdef USE_SHADOW |
102 | struct spwd *spw = NULL; | 102 | struct spwd *spw = NULL; |
@@ -154,22 +154,28 @@ allowed_user(struct passwd * pw) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Get the shell from the password data. An empty shell field is | 157 | * Deny if shell does not exist or is not executable unless we |
158 | * legal, and means /bin/sh. | 158 | * are chrooting. |
159 | */ | 159 | */ |
160 | shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; | 160 | if (options.chroot_directory == NULL || |
161 | 161 | strcasecmp(options.chroot_directory, "none") == 0) { | |
162 | /* deny if shell does not exists or is not executable */ | 162 | char *shell = xstrdup((pw->pw_shell[0] == '\0') ? |
163 | if (stat(shell, &st) != 0) { | 163 | _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */ |
164 | logit("User %.100s not allowed because shell %.100s does not exist", | 164 | |
165 | pw->pw_name, shell); | 165 | if (stat(shell, &st) != 0) { |
166 | return 0; | 166 | logit("User %.100s not allowed because shell %.100s " |
167 | } | 167 | "does not exist", pw->pw_name, shell); |
168 | if (S_ISREG(st.st_mode) == 0 || | 168 | xfree(shell); |
169 | (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { | 169 | return 0; |
170 | logit("User %.100s not allowed because shell %.100s is not executable", | 170 | } |
171 | pw->pw_name, shell); | 171 | if (S_ISREG(st.st_mode) == 0 || |
172 | return 0; | 172 | (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { |
173 | logit("User %.100s not allowed because shell %.100s " | ||
174 | "is not executable", pw->pw_name, shell); | ||
175 | xfree(shell); | ||
176 | return 0; | ||
177 | } | ||
178 | xfree(shell); | ||
173 | } | 179 | } |
174 | 180 | ||
175 | if (options.num_deny_users > 0 || options.num_allow_users > 0 || | 181 | if (options.num_deny_users > 0 || options.num_allow_users > 0 || |
@@ -399,38 +405,6 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, | |||
399 | return host_status; | 405 | return host_status; |
400 | } | 406 | } |
401 | 407 | ||
402 | int | ||
403 | reject_blacklisted_key(Key *key, int hostkey) | ||
404 | { | ||
405 | char *fp; | ||
406 | |||
407 | if (blacklisted_key(key, &fp) != 1) | ||
408 | return 0; | ||
409 | |||
410 | if (options.permit_blacklisted_keys) { | ||
411 | if (hostkey) | ||
412 | error("Host key %s blacklisted (see " | ||
413 | "ssh-vulnkey(1)); continuing anyway", fp); | ||
414 | else | ||
415 | logit("Public key %s from %s blacklisted (see " | ||
416 | "ssh-vulnkey(1)); continuing anyway", | ||
417 | fp, get_remote_ipaddr()); | ||
418 | xfree(fp); | ||
419 | } else { | ||
420 | if (hostkey) | ||
421 | error("Host key %s blacklisted (see " | ||
422 | "ssh-vulnkey(1))", fp); | ||
423 | else | ||
424 | logit("Public key %s from %s blacklisted (see " | ||
425 | "ssh-vulnkey(1))", | ||
426 | fp, get_remote_ipaddr()); | ||
427 | xfree(fp); | ||
428 | return 1; | ||
429 | } | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | 408 | ||
435 | /* | 409 | /* |
436 | * Check a given file for security. This is defined as all components | 410 | * Check a given file for security. This is defined as all components |
@@ -488,7 +462,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, | |||
488 | return -1; | 462 | return -1; |
489 | } | 463 | } |
490 | 464 | ||
491 | /* If are passed the homedir then we can stop */ | 465 | /* If are past the homedir then we can stop */ |
492 | if (comparehome && strcmp(homedir, buf) == 0) { | 466 | if (comparehome && strcmp(homedir, buf) == 0) { |
493 | debug3("secure_filename: terminating check at '%s'", | 467 | debug3("secure_filename: terminating check at '%s'", |
494 | buf); | 468 | buf); |
@@ -562,7 +536,28 @@ getpwnamallow(const char *user) | |||
562 | parse_server_match_config(&options, user, | 536 | parse_server_match_config(&options, user, |
563 | get_canonical_hostname(options.use_dns), get_remote_ipaddr()); | 537 | get_canonical_hostname(options.use_dns), get_remote_ipaddr()); |
564 | 538 | ||
539 | #if defined(_AIX) && defined(HAVE_SETAUTHDB) | ||
540 | aix_setauthdb(user); | ||
541 | #endif | ||
542 | |||
565 | pw = getpwnam(user); | 543 | pw = getpwnam(user); |
544 | |||
545 | #if defined(_AIX) && defined(HAVE_SETAUTHDB) | ||
546 | aix_restoreauthdb(); | ||
547 | #endif | ||
548 | #ifdef HAVE_CYGWIN | ||
549 | /* | ||
550 | * Windows usernames are case-insensitive. To avoid later problems | ||
551 | * when trying to match the username, the user is only allowed to | ||
552 | * login if the username is given in the same case as stored in the | ||
553 | * user database. | ||
554 | */ | ||
555 | if (pw != NULL && strcmp(user, pw->pw_name) != 0) { | ||
556 | logit("Login name %.100s does not match stored username %.100s", | ||
557 | user, pw->pw_name); | ||
558 | pw = NULL; | ||
559 | } | ||
560 | #endif | ||
566 | if (pw == NULL) { | 561 | if (pw == NULL) { |
567 | logit("Invalid user %.100s from %.100s", | 562 | logit("Invalid user %.100s from %.100s", |
568 | user, get_remote_ipaddr()); | 563 | user, get_remote_ipaddr()); |
@@ -597,6 +592,59 @@ getpwnamallow(const char *user) | |||
597 | return (NULL); | 592 | return (NULL); |
598 | } | 593 | } |
599 | 594 | ||
595 | /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */ | ||
596 | int | ||
597 | auth_key_is_revoked(Key *key, int hostkey) | ||
598 | { | ||
599 | char *key_fp; | ||
600 | |||
601 | if (blacklisted_key(key, &key_fp) == 1) { | ||
602 | if (options.permit_blacklisted_keys) { | ||
603 | if (hostkey) | ||
604 | error("Host key %s blacklisted (see " | ||
605 | "ssh-vulnkey(1)); continuing anyway", | ||
606 | key_fp); | ||
607 | else | ||
608 | logit("Public key %s from %s blacklisted (see " | ||
609 | "ssh-vulnkey(1)); continuing anyway", | ||
610 | key_fp, get_remote_ipaddr()); | ||
611 | xfree(key_fp); | ||
612 | } else { | ||
613 | if (hostkey) | ||
614 | error("Host key %s blacklisted (see " | ||
615 | "ssh-vulnkey(1))", key_fp); | ||
616 | else | ||
617 | logit("Public key %s from %s blacklisted (see " | ||
618 | "ssh-vulnkey(1))", | ||
619 | key_fp, get_remote_ipaddr()); | ||
620 | xfree(key_fp); | ||
621 | return 1; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | if (options.revoked_keys_file == NULL) | ||
626 | return 0; | ||
627 | |||
628 | switch (key_in_file(key, options.revoked_keys_file, 0)) { | ||
629 | case 0: | ||
630 | /* key not revoked */ | ||
631 | return 0; | ||
632 | case -1: | ||
633 | /* Error opening revoked_keys_file: refuse all keys */ | ||
634 | error("Revoked keys file is unreadable: refusing public key " | ||
635 | "authentication"); | ||
636 | return 1; | ||
637 | case 1: | ||
638 | /* Key revoked */ | ||
639 | key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); | ||
640 | error("WARNING: authentication attempt with a revoked " | ||
641 | "%s key %s ", key_type(key), key_fp); | ||
642 | xfree(key_fp); | ||
643 | return 1; | ||
644 | } | ||
645 | fatal("key_in_file returned junk"); | ||
646 | } | ||
647 | |||
600 | void | 648 | void |
601 | auth_debug_add(const char *fmt,...) | 649 | auth_debug_add(const char *fmt,...) |
602 | { | 650 | { |