summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2008-02-10 22:40:12 +1100
committerDamien Miller <djm@mindrot.org>2008-02-10 22:40:12 +1100
commitd8cb1f184f9acaae02bb4d15ce1e00ffbeeeac88 (patch)
treefb0100a74a6c870e835706aa487b54500510c5e1 /session.c
parentdfc24258a75a06ea8a3f56d99d3669e1a012a1dc (diff)
- djm@cvs.openbsd.org 2008/02/08 23:24:07
[servconf.c servconf.h session.c sftp-server.c sftp.h sshd_config] [sshd_config.5] add sshd_config ChrootDirectory option to chroot(2) users to a directory and tweak internal sftp server to work with it (no special files in chroot required). ok markus@
Diffstat (limited to 'session.c')
-rw-r--r--session.c106
1 files changed, 93 insertions, 13 deletions
diff --git a/session.c b/session.c
index a1319b384..1768c8c2f 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.225 2008/02/04 21:53:00 markus Exp $ */ 1/* $OpenBSD: session.c,v 1.226 2008/02/08 23:24:07 djm 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
@@ -84,6 +84,7 @@
84#include "sshlogin.h" 84#include "sshlogin.h"
85#include "serverloop.h" 85#include "serverloop.h"
86#include "canohost.h" 86#include "canohost.h"
87#include "misc.h"
87#include "session.h" 88#include "session.h"
88#include "kex.h" 89#include "kex.h"
89#include "monitor_wrap.h" 90#include "monitor_wrap.h"
@@ -93,6 +94,9 @@
93#include <kafs.h> 94#include <kafs.h>
94#endif 95#endif
95 96
97/* Magic name for internal sftp-server */
98#define INTERNAL_SFTP_NAME "internal-sftp"
99
96/* func */ 100/* func */
97 101
98Session *session_new(void); 102Session *session_new(void);
@@ -130,7 +134,7 @@ extern Buffer loginmsg;
130const char *original_command = NULL; 134const char *original_command = NULL;
131 135
132/* data */ 136/* data */
133#define MAX_SESSIONS 10 137#define MAX_SESSIONS 20
134Session sessions[MAX_SESSIONS]; 138Session sessions[MAX_SESSIONS];
135 139
136#define SUBSYSTEM_NONE 0 140#define SUBSYSTEM_NONE 0
@@ -688,13 +692,17 @@ do_exec(Session *s, const char *command)
688 if (options.adm_forced_command) { 692 if (options.adm_forced_command) {
689 original_command = command; 693 original_command = command;
690 command = options.adm_forced_command; 694 command = options.adm_forced_command;
691 if (s->is_subsystem) 695 if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
696 s->is_subsystem = SUBSYSTEM_INT_SFTP;
697 else if (s->is_subsystem)
692 s->is_subsystem = SUBSYSTEM_EXT; 698 s->is_subsystem = SUBSYSTEM_EXT;
693 debug("Forced command (config) '%.900s'", command); 699 debug("Forced command (config) '%.900s'", command);
694 } else if (forced_command) { 700 } else if (forced_command) {
695 original_command = command; 701 original_command = command;
696 command = forced_command; 702 command = forced_command;
697 if (s->is_subsystem) 703 if (strcmp(INTERNAL_SFTP_NAME, command) == 0)
704 s->is_subsystem = SUBSYSTEM_INT_SFTP;
705 else if (s->is_subsystem)
698 s->is_subsystem = SUBSYSTEM_EXT; 706 s->is_subsystem = SUBSYSTEM_EXT;
699 debug("Forced command (key option) '%.900s'", command); 707 debug("Forced command (key option) '%.900s'", command);
700 } 708 }
@@ -710,7 +718,6 @@ do_exec(Session *s, const char *command)
710 PRIVSEP(audit_run_command(shell)); 718 PRIVSEP(audit_run_command(shell));
711 } 719 }
712#endif 720#endif
713
714 if (s->ttyfd != -1) 721 if (s->ttyfd != -1)
715 do_exec_pty(s, command); 722 do_exec_pty(s, command);
716 else 723 else
@@ -1293,6 +1300,61 @@ do_nologin(struct passwd *pw)
1293 } 1300 }
1294} 1301}
1295 1302
1303/*
1304 * Chroot into a directory after checking it for safety: all path components
1305 * must be root-owned directories with strict permissions.
1306 */
1307static void
1308safely_chroot(const char *path, uid_t uid)
1309{
1310 const char *cp;
1311 char component[MAXPATHLEN];
1312 struct stat st;
1313
1314 if (*path != '/')
1315 fatal("chroot path does not begin at root");
1316 if (strlen(path) >= sizeof(component))
1317 fatal("chroot path too long");
1318
1319 /*
1320 * Descend the path, checking that each component is a
1321 * root-owned directory with strict permissions.
1322 */
1323 for (cp = path; cp != NULL;) {
1324 if ((cp = strchr(cp, '/')) == NULL)
1325 strlcpy(component, path, sizeof(component));
1326 else {
1327 cp++;
1328 memcpy(component, path, cp - path);
1329 component[cp - path] = '\0';
1330 }
1331
1332 debug3("%s: checking '%s'", __func__, component);
1333
1334 if (stat(component, &st) != 0)
1335 fatal("%s: stat(\"%s\"): %s", __func__,
1336 component, strerror(errno));
1337 if (st.st_uid != 0 || (st.st_mode & 022) != 0)
1338 fatal("bad ownership or modes for chroot "
1339 "directory %s\"%s\"",
1340 cp == NULL ? "" : "component ", component);
1341 if (!S_ISDIR(st.st_mode))
1342 fatal("chroot path %s\"%s\" is not a directory",
1343 cp == NULL ? "" : "component ", component);
1344
1345 }
1346
1347 if (chdir(path) == -1)
1348 fatal("Unable to chdir to chroot path \"%s\": "
1349 "%s", path, strerror(errno));
1350 if (chroot(path) == -1)
1351 fatal("chroot(\"%s\"): %s", path, strerror(errno));
1352 if (chdir("/") == -1)
1353 fatal("%s: chdir(/) after chroot: %s",
1354 __func__, strerror(errno));
1355 verbose("Changed root directory to \"%s\"", path);
1356}
1357
1296/* Set login name, uid, gid, and groups. */ 1358/* Set login name, uid, gid, and groups. */
1297void 1359void
1298do_setusercontext(struct passwd *pw) 1360do_setusercontext(struct passwd *pw)
@@ -1324,7 +1386,7 @@ do_setusercontext(struct passwd *pw)
1324 } 1386 }
1325# endif /* USE_PAM */ 1387# endif /* USE_PAM */
1326 if (setusercontext(lc, pw, pw->pw_uid, 1388 if (setusercontext(lc, pw, pw->pw_uid,
1327 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { 1389 (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
1328 perror("unable to set user context"); 1390 perror("unable to set user context");
1329 exit(1); 1391 exit(1);
1330 } 1392 }
@@ -1347,13 +1409,13 @@ do_setusercontext(struct passwd *pw)
1347 exit(1); 1409 exit(1);
1348 } 1410 }
1349 endgrent(); 1411 endgrent();
1350#ifdef GSSAPI 1412# ifdef GSSAPI
1351 if (options.gss_authentication) { 1413 if (options.gss_authentication) {
1352 temporarily_use_uid(pw); 1414 temporarily_use_uid(pw);
1353 ssh_gssapi_storecreds(); 1415 ssh_gssapi_storecreds();
1354 restore_uid(); 1416 restore_uid();
1355 } 1417 }
1356#endif 1418# endif
1357# ifdef USE_PAM 1419# ifdef USE_PAM
1358 /* 1420 /*
1359 * PAM credentials may take the form of supplementary groups. 1421 * PAM credentials may take the form of supplementary groups.
@@ -1367,15 +1429,33 @@ do_setusercontext(struct passwd *pw)
1367# endif /* USE_PAM */ 1429# endif /* USE_PAM */
1368# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) 1430# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
1369 irix_setusercontext(pw); 1431 irix_setusercontext(pw);
1370# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ 1432# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
1371# ifdef _AIX 1433# ifdef _AIX
1372 aix_usrinfo(pw); 1434 aix_usrinfo(pw);
1373# endif /* _AIX */ 1435# endif /* _AIX */
1374#ifdef USE_LIBIAF 1436# ifdef USE_LIBIAF
1375 if (set_id(pw->pw_name) != 0) { 1437 if (set_id(pw->pw_name) != 0) {
1376 exit(1); 1438 exit(1);
1377 } 1439 }
1378#endif /* USE_LIBIAF */ 1440# endif /* USE_LIBIAF */
1441#endif
1442
1443 if (options.chroot_directory != NULL &&
1444 strcasecmp(options.chroot_directory, "none") != 0) {
1445 char *chroot_path;
1446
1447 chroot_path = percent_expand(options.chroot_directory,
1448 "h", pw->pw_dir, "u", pw->pw_name, (char *)NULL);
1449 safely_chroot(chroot_path, pw->pw_uid);
1450 free(chroot_path);
1451 }
1452
1453#ifdef HAVE_LOGIN_CAP
1454 if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
1455 perror("unable to set user context (setuser)");
1456 exit(1);
1457 }
1458#else
1379 /* Permanently switch to the desired uid. */ 1459 /* Permanently switch to the desired uid. */
1380 permanently_set_uid(pw); 1460 permanently_set_uid(pw);
1381#endif 1461#endif
@@ -1625,7 +1705,7 @@ do_child(Session *s, const char *command)
1625 argv[i] = NULL; 1705 argv[i] = NULL;
1626 optind = optreset = 1; 1706 optind = optreset = 1;
1627 __progname = argv[0]; 1707 __progname = argv[0];
1628 exit(sftp_server_main(i, argv)); 1708 exit(sftp_server_main(i, argv, s->pw));
1629 } 1709 }
1630 1710
1631 if (options.use_login) { 1711 if (options.use_login) {
@@ -1900,7 +1980,7 @@ session_subsystem_req(Session *s)
1900 if (strcmp(subsys, options.subsystem_name[i]) == 0) { 1980 if (strcmp(subsys, options.subsystem_name[i]) == 0) {
1901 prog = options.subsystem_command[i]; 1981 prog = options.subsystem_command[i];
1902 cmd = options.subsystem_args[i]; 1982 cmd = options.subsystem_args[i];
1903 if (!strcmp("internal-sftp", prog)) { 1983 if (!strcmp(INTERNAL_SFTP_NAME, prog)) {
1904 s->is_subsystem = SUBSYSTEM_INT_SFTP; 1984 s->is_subsystem = SUBSYSTEM_INT_SFTP;
1905 } else if (stat(prog, &st) < 0) { 1985 } else if (stat(prog, &st) < 0) {
1906 error("subsystem: cannot stat %s: %s", prog, 1986 error("subsystem: cannot stat %s: %s", prog,