[PATCH] Add a chroot_users option to sshd

Gary Fernandez GaryF at livevault.com
Wed Nov 6 02:48:44 EST 2002


This patch adds a new option to sshd, chroot_users. It has the effect of
chroot()ing incoming ssh users to their home directory. Note: this option
does not work if UsePrivilegeSeparation is enabled.

Patch is based on OpenSSH 3.4p1.

*** servconf.h@@\main\1 Tue Oct  1 17:25:32 2002
--- servconf.h Wed Oct  2 06:17:48 2002
***************
*** 131,136 ****
--- 131,137 ----
  	char   *authorized_keys_file;	/* File containing public keys */
  	char   *authorized_keys_file2;
  	int	pam_authentication_via_kbd_int;
+ 	int    chroot_users;
  }       ServerOptions;
  
  void	 initialize_server_options(ServerOptions *);

*** servconf.c@@\main\1 Tue Oct  1 17:25:26 2002
--- servconf.c Wed Oct  2 06:09:06 2002
***************
*** 122,127 ****
--- 122,128 ----
  	options->client_alive_count_max = -1;
  	options->authorized_keys_file = NULL;
  	options->authorized_keys_file2 = NULL;
+ 	options->chroot_users = -1;
  
  	/* Needs to be accessable in many places */
  	use_privsep = -1;
***************
*** 253,258 ****
--- 254,262 ----
  	if (options->authorized_keys_file == NULL)
  		options->authorized_keys_file =
_PATH_SSH_USER_PERMITTED_KEYS;
  
+ 	if (options->chroot_users == -1)
+ 		options->chroot_users = 0;
+ 
  	/* Turn privilege separation on by default */
  	if (use_privsep == -1)
  		use_privsep = 1;
***************
*** 298,304 ****
  	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
  	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
  	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
! 	sUsePrivilegeSeparation,
  	sDeprecated
  } ServerOpCodes;
  
--- 302,308 ----
  	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
  	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
  	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
! 	sUsePrivilegeSeparation, sChrootUsers,
  	sDeprecated
  } ServerOpCodes;
  
***************
*** 375,380 ****
--- 379,385 ----
  	{ "clientalivecountmax", sClientAliveCountMax },
  	{ "authorizedkeysfile", sAuthorizedKeysFile },
  	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+ 	{ "chrootusers", sChrootUsers },
  	{ "useprivilegeseparation", sUsePrivilegeSeparation},
  	{ NULL, sBadOption }
  };
***************
*** 900,905 ****
--- 905,914 ----
  	case sClientAliveCountMax:
  		intptr = &options->client_alive_count_max;
  		goto parse_int;
+ 
+ 	case sChrootUsers:
+ 		intptr = &options->chroot_users;
+ 		goto parse_flag;
  
  	case sDeprecated:
  		log("%s line %d: Deprecated option %s",

*** session.c@@\main\1 Tue Oct  1 17:25:48 2002
--- session.c Tue Nov  5 09:59:14 2002
***************
*** 99,104 ****
--- 99,111 ----
  /* original command from peer. */
  const char *original_command = NULL;
  
+ /* option to use filesystem snapshot */
+ /* #define DO_SNAPSHOTS */
+ #ifdef DO_SNAPSHOTS
+ /* snapshot name */
+ char *snapshot = NULL;
+ #endif
+ 
  /* data */
  #define MAX_SESSIONS 10
  Session	sessions[MAX_SESSIONS];
***************
*** 1255,1260 ****
--- 1262,1268 ----
  	const char *shell, *shell0, *hostname = NULL;
  	struct passwd *pw = s->pw;
  	u_int i;
+ 	char *idx = NULL;
  
  	/* remove hostkey from the child's memory */
  	destroy_sensitive_data();
***************
*** 1274,1279 ****
--- 1282,1330 ----
  			do_motd();
  #else /* HAVE_OSF_SIA */
  		do_nologin(pw);
+ #ifdef DO_SNAPSHOTS
+ #define SNAPSHOT "snapshot!"
+ 		if ((snapshot == NULL || (snapshot != NULL && snapshot[0] ==
'\0')) && command != NULL && !strncmp(command, SNAPSHOT, strlen(SNAPSHOT)))
{
+ 			idx = strchr(command, ',');
+ 			if (snapshot == NULL)
+ 				snapshot = xmalloc(128);
+ 			strncpy(snapshot, command+strlen(SNAPSHOT), idx -
(command + strlen(SNAPSHOT)));
+ 		}
+ 		if (snapshot != NULL && snapshot[0] != '\0') {
+ 			char home[MAXPATHLEN];
+ 			char *current;
+ 			current = strstr(pw->pw_dir, "current");
+ 			if (current != NULL) {
+ 				strncpy(home, pw->pw_dir, current -
pw->pw_dir);
+ 				home[current-pw->pw_dir] = '\0';
+ 				strcat(home, snapshot);
+ 				strcat(home, current + strlen("current") );
+ 			}
+ 			else
+ 				strcpy(home, pw->pw_dir);
+ 			if (chroot(home) < 0) {
+ 				fprintf(stderr, "Could not chroot to home
directory %s: %s\n",
+ 					home, strerror(errno));
+ 				strcpy(home, pw->pw_dir);
+ 				if (chroot(home) < 0) {
+ 					fprintf(stderr, "Could not chroot to
home directory %s: %s\n",
+ 						home, strerror(errno));
+ 				}
+ 			}
+ 			if (idx != NULL)
+ 				command = idx + 1;
+ 		}
+ 		else {
+ #endif /* DO_SNAPSHOTS */
+ 			if (options.chroot_users) {
+ 				if (chroot(pw->pw_dir) < 0) {
+ 					fprintf(stderr, "Could not chroot to
home directory %s: %s\n",
+ 						pw->pw_dir,
strerror(errno));
+ 				}
+ 			}
+ #ifdef DO_SNAPSHOTS
+ 		}
+ #endif
  		do_setusercontext(pw);
  #endif /* HAVE_OSF_SIA */
  	}
***************
*** 1347,1353 ****
  #endif /* AFS */
  
  	/* Change current directory to the user\'s home directory. */
! 	if (chdir(pw->pw_dir) < 0) {
  		fprintf(stderr, "Could not chdir to home directory %s:
%s\n",
  		    pw->pw_dir, strerror(errno));
  #ifdef HAVE_LOGIN_CAP
--- 1398,1411 ----
  #endif /* AFS */
  
  	/* Change current directory to the user\'s home directory. */
! 	if (options.chroot_users) {
! 	   if (chdir("/") < 0) {
! 	      fprintf(stderr, "Could not chdir to home directory %s: %s\n",
! 	      pw->pw_dir, strerror(errno));
! 	   }
! 	}
! 	else {
! 	   if (chdir(pw->pw_dir) < 0) {
  		fprintf(stderr, "Could not chdir to home directory %s:
%s\n",
  		    pw->pw_dir, strerror(errno));
  #ifdef HAVE_LOGIN_CAP
***************
*** 1354,1359 ****
--- 1412,1418 ----
  		if (login_getcapbool(lc, "requirehome", 0))
  			exit(1);
  #endif
+ 	   }
  	}
  
  	if (!options.use_login)
***************
*** 1613,1618 ****
--- 1672,1678 ----
  	int success = 0;
  	char *cmd, *subsys = packet_get_string(&len);
  	int i;
+ 	char *idx;
  
  	packet_check_eom();
  	log("subsystem request for %.100s", subsys);
***************
*** 1620,1625 ****
--- 1680,1697 ----
  	for (i = 0; i < options.num_subsystems; i++) {
  		if (strcmp(subsys, options.subsystem_name[i]) == 0) {
  			cmd = options.subsystem_command[i];
+ #ifdef DO_SNAPSHOTS
+ 			if (snapshot == NULL)
+ 			   snapshot = xmalloc(128);
+ 			snapshot[0] = '\0';
+ 			if (!strncmp(cmd, SNAPSHOT, strlen(SNAPSHOT))) {
+ 			   idx = strchr(cmd, ',');
+ 			   strncpy(snapshot, cmd + strlen(SNAPSHOT),
+ 				   idx - (cmd + strlen(SNAPSHOT)));
+ 			   snapshot[idx - (cmd + strlen(SNAPSHOT))] = '\0';
+ 			   cmd = idx + 1;
+ 			}
+ #endif
  			if (stat(cmd, &st) < 0) {
  				error("subsystem: cannot stat %s: %s", cmd,
  				    strerror(errno));




More information about the openssh-unix-dev mailing list