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 /session.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 'session.c')
-rw-r--r-- | session.c | 106 |
1 files changed, 70 insertions, 36 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.246 2009/04/17 19:23:06 stevesk Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.252 2010/03/07 11:57:13 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -142,9 +142,10 @@ static int sessions_first_unused = -1; | |||
142 | static int sessions_nalloc = 0; | 142 | static int sessions_nalloc = 0; |
143 | static Session *sessions = NULL; | 143 | static Session *sessions = NULL; |
144 | 144 | ||
145 | #define SUBSYSTEM_NONE 0 | 145 | #define SUBSYSTEM_NONE 0 |
146 | #define SUBSYSTEM_EXT 1 | 146 | #define SUBSYSTEM_EXT 1 |
147 | #define SUBSYSTEM_INT_SFTP 2 | 147 | #define SUBSYSTEM_INT_SFTP 2 |
148 | #define SUBSYSTEM_INT_SFTP_ERROR 3 | ||
148 | 149 | ||
149 | #ifdef HAVE_LOGIN_CAP | 150 | #ifdef HAVE_LOGIN_CAP |
150 | login_cap_t *lc; | 151 | login_cap_t *lc; |
@@ -270,6 +271,8 @@ do_authenticated(Authctxt *authctxt) | |||
270 | if (!no_port_forwarding_flag && options.allow_tcp_forwarding) | 271 | if (!no_port_forwarding_flag && options.allow_tcp_forwarding) |
271 | channel_permit_all_opens(); | 272 | channel_permit_all_opens(); |
272 | 273 | ||
274 | auth_debug_send(); | ||
275 | |||
273 | if (compat20) | 276 | if (compat20) |
274 | do_authenticated2(authctxt); | 277 | do_authenticated2(authctxt); |
275 | else | 278 | else |
@@ -785,17 +788,19 @@ do_exec(Session *s, const char *command) | |||
785 | if (options.adm_forced_command) { | 788 | if (options.adm_forced_command) { |
786 | original_command = command; | 789 | original_command = command; |
787 | command = options.adm_forced_command; | 790 | command = options.adm_forced_command; |
788 | if (IS_INTERNAL_SFTP(command)) | 791 | if (IS_INTERNAL_SFTP(command)) { |
789 | s->is_subsystem = SUBSYSTEM_INT_SFTP; | 792 | s->is_subsystem = s->is_subsystem ? |
790 | else if (s->is_subsystem) | 793 | SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; |
794 | } else if (s->is_subsystem) | ||
791 | s->is_subsystem = SUBSYSTEM_EXT; | 795 | s->is_subsystem = SUBSYSTEM_EXT; |
792 | debug("Forced command (config) '%.900s'", command); | 796 | debug("Forced command (config) '%.900s'", command); |
793 | } else if (forced_command) { | 797 | } else if (forced_command) { |
794 | original_command = command; | 798 | original_command = command; |
795 | command = forced_command; | 799 | command = forced_command; |
796 | if (IS_INTERNAL_SFTP(command)) | 800 | if (IS_INTERNAL_SFTP(command)) { |
797 | s->is_subsystem = SUBSYSTEM_INT_SFTP; | 801 | s->is_subsystem = s->is_subsystem ? |
798 | else if (s->is_subsystem) | 802 | SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; |
803 | } else if (s->is_subsystem) | ||
799 | s->is_subsystem = SUBSYSTEM_EXT; | 804 | s->is_subsystem = SUBSYSTEM_EXT; |
800 | debug("Forced command (key option) '%.900s'", command); | 805 | debug("Forced command (key option) '%.900s'", command); |
801 | } | 806 | } |
@@ -1374,26 +1379,32 @@ static void | |||
1374 | do_nologin(struct passwd *pw) | 1379 | do_nologin(struct passwd *pw) |
1375 | { | 1380 | { |
1376 | FILE *f = NULL; | 1381 | FILE *f = NULL; |
1377 | char buf[1024]; | 1382 | char buf[1024], *nl, *def_nl = _PATH_NOLOGIN; |
1383 | struct stat sb; | ||
1378 | 1384 | ||
1379 | #ifdef HAVE_LOGIN_CAP | 1385 | #ifdef HAVE_LOGIN_CAP |
1380 | if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) | 1386 | if (login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) |
1381 | f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, | 1387 | return; |
1382 | _PATH_NOLOGIN), "r"); | 1388 | nl = login_getcapstr(lc, "nologin", def_nl, def_nl); |
1383 | #else | 1389 | #else |
1384 | if (pw->pw_uid) | 1390 | if (pw->pw_uid == 0) |
1385 | f = fopen(_PATH_NOLOGIN, "r"); | 1391 | return; |
1392 | nl = def_nl; | ||
1386 | #endif | 1393 | #endif |
1387 | if (f) { | 1394 | if (stat(nl, &sb) == -1) { |
1388 | /* /etc/nologin exists. Print its contents and exit. */ | 1395 | if (nl != def_nl) |
1389 | logit("User %.100s not allowed because %s exists", | 1396 | xfree(nl); |
1390 | pw->pw_name, _PATH_NOLOGIN); | 1397 | return; |
1391 | while (fgets(buf, sizeof(buf), f)) | ||
1392 | fputs(buf, stderr); | ||
1393 | fclose(f); | ||
1394 | fflush(NULL); | ||
1395 | exit(254); | ||
1396 | } | 1398 | } |
1399 | |||
1400 | /* /etc/nologin exists. Print its contents if we can and exit. */ | ||
1401 | logit("User %.100s not allowed because %s exists", pw->pw_name, nl); | ||
1402 | if ((f = fopen(nl, "r")) != NULL) { | ||
1403 | while (fgets(buf, sizeof(buf), f)) | ||
1404 | fputs(buf, stderr); | ||
1405 | fclose(f); | ||
1406 | } | ||
1407 | exit(254); | ||
1397 | } | 1408 | } |
1398 | 1409 | ||
1399 | /* | 1410 | /* |
@@ -1521,6 +1532,24 @@ do_setusercontext(struct passwd *pw) | |||
1521 | } | 1532 | } |
1522 | # endif /* USE_LIBIAF */ | 1533 | # endif /* USE_LIBIAF */ |
1523 | #endif | 1534 | #endif |
1535 | #ifdef HAVE_SETPCRED | ||
1536 | /* | ||
1537 | * If we have a chroot directory, we set all creds except real | ||
1538 | * uid which we will need for chroot. If we don't have a | ||
1539 | * chroot directory, we don't override anything. | ||
1540 | */ | ||
1541 | { | ||
1542 | char **creds = NULL, *chroot_creds[] = | ||
1543 | { "REAL_USER=root", NULL }; | ||
1544 | |||
1545 | if (options.chroot_directory != NULL && | ||
1546 | strcasecmp(options.chroot_directory, "none") != 0) | ||
1547 | creds = chroot_creds; | ||
1548 | |||
1549 | if (setpcred(pw->pw_name, creds) == -1) | ||
1550 | fatal("Failed to set process credentials"); | ||
1551 | } | ||
1552 | #endif /* HAVE_SETPCRED */ | ||
1524 | 1553 | ||
1525 | #ifdef WITH_SELINUX | 1554 | #ifdef WITH_SELINUX |
1526 | ssh_selinux_setup_exec_context(pw->pw_name); | 1555 | ssh_selinux_setup_exec_context(pw->pw_name); |
@@ -1537,10 +1566,6 @@ do_setusercontext(struct passwd *pw) | |||
1537 | free(chroot_path); | 1566 | free(chroot_path); |
1538 | } | 1567 | } |
1539 | 1568 | ||
1540 | #ifdef HAVE_SETPCRED | ||
1541 | if (setpcred(pw->pw_name, (char **)NULL) == -1) | ||
1542 | fatal("Failed to set process credentials"); | ||
1543 | #endif /* HAVE_SETPCRED */ | ||
1544 | #ifdef HAVE_LOGIN_CAP | 1569 | #ifdef HAVE_LOGIN_CAP |
1545 | if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) { | 1570 | if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) { |
1546 | perror("unable to set user context (setuser)"); | 1571 | perror("unable to set user context (setuser)"); |
@@ -1783,7 +1808,11 @@ do_child(Session *s, const char *command) | |||
1783 | /* restore SIGPIPE for child */ | 1808 | /* restore SIGPIPE for child */ |
1784 | signal(SIGPIPE, SIG_DFL); | 1809 | signal(SIGPIPE, SIG_DFL); |
1785 | 1810 | ||
1786 | if (s->is_subsystem == SUBSYSTEM_INT_SFTP) { | 1811 | if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) { |
1812 | printf("This service allows sftp connections only.\n"); | ||
1813 | fflush(NULL); | ||
1814 | exit(1); | ||
1815 | } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) { | ||
1787 | extern int optind, optreset; | 1816 | extern int optind, optreset; |
1788 | int i; | 1817 | int i; |
1789 | char *p, *args; | 1818 | char *p, *args; |
@@ -1796,9 +1825,14 @@ do_child(Session *s, const char *command) | |||
1796 | argv[i] = NULL; | 1825 | argv[i] = NULL; |
1797 | optind = optreset = 1; | 1826 | optind = optreset = 1; |
1798 | __progname = argv[0]; | 1827 | __progname = argv[0]; |
1828 | #ifdef WITH_SELINUX | ||
1829 | ssh_selinux_change_context("sftpd_t"); | ||
1830 | #endif | ||
1799 | exit(sftp_server_main(i, argv, s->pw)); | 1831 | exit(sftp_server_main(i, argv, s->pw)); |
1800 | } | 1832 | } |
1801 | 1833 | ||
1834 | fflush(NULL); | ||
1835 | |||
1802 | if (options.use_login) { | 1836 | if (options.use_login) { |
1803 | launch_login(pw, hostname); | 1837 | launch_login(pw, hostname); |
1804 | /* NEVERREACHED */ | 1838 | /* NEVERREACHED */ |
@@ -2109,16 +2143,16 @@ session_subsystem_req(Session *s) | |||
2109 | if (strcmp(subsys, options.subsystem_name[i]) == 0) { | 2143 | if (strcmp(subsys, options.subsystem_name[i]) == 0) { |
2110 | prog = options.subsystem_command[i]; | 2144 | prog = options.subsystem_command[i]; |
2111 | cmd = options.subsystem_args[i]; | 2145 | cmd = options.subsystem_args[i]; |
2112 | if (!strcmp(INTERNAL_SFTP_NAME, prog)) { | 2146 | if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) { |
2113 | s->is_subsystem = SUBSYSTEM_INT_SFTP; | 2147 | s->is_subsystem = SUBSYSTEM_INT_SFTP; |
2114 | } else if (stat(prog, &st) < 0) { | 2148 | debug("subsystem: %s", prog); |
2115 | error("subsystem: cannot stat %s: %s", prog, | ||
2116 | strerror(errno)); | ||
2117 | break; | ||
2118 | } else { | 2149 | } else { |
2150 | if (stat(prog, &st) < 0) | ||
2151 | debug("subsystem: cannot stat %s: %s", | ||
2152 | prog, strerror(errno)); | ||
2119 | s->is_subsystem = SUBSYSTEM_EXT; | 2153 | s->is_subsystem = SUBSYSTEM_EXT; |
2154 | debug("subsystem: exec() %s", cmd); | ||
2120 | } | 2155 | } |
2121 | debug("subsystem: exec() %s", cmd); | ||
2122 | success = do_exec(s, cmd) == 0; | 2156 | success = do_exec(s, cmd) == 0; |
2123 | break; | 2157 | break; |
2124 | } | 2158 | } |