chroot sftp-server [PATCH]

mouring at etoh.eviladmin.org mouring at etoh.eviladmin.org
Thu May 24 13:53:21 EST 2001



Outside the fact that realpath() requires the file aspect of the path to
exist which breaks 'rename' and 'symlink' =)

- Ben

On Wed, 23 May 2001 mouring at etoh.eviladmin.org wrote:

>
>
> On 23 May 2001, Patrick Higgins wrote:
>
> > I'm working on setting up a semi-trusted sftp service, and to get it
> > working, I need chroot capability.
> >
> Actually I was looking at it from a different point of view.
>
> Instead of requiring setuid sftp-sever and the use of chroot().  Carefully
> crafted realpath() usage and strncmp() should do the same thing.
>
> This is a VERY VERY limited test.  (As in.. compiles.. and looks like it
> works.=)
>
> I know it can be cleaned up.. but it's where I left off in my testing.
>
> Markus, is there anything else I should worry about using this method?
>
> - Ben
>
>
> --- ../cvs/OpenSSH/src/usr.bin/ssh/sftp-server.c	Thu Apr  5 05:42:53 2001
> +++ sftp-server.c	Wed May 23 19:54:06 2001
> @@ -357,6 +357,33 @@
>
>  /* parse incoming */
>
> +char *jailpath;
> +
> +char*
> +getpath(u_int32_t id)
> +{
> +	char resolvedpath[MAXPATHLEN];
> +	char *path;
> +
> +	path = get_string(NULL);
> +
> +        if (realpath(path, resolvedpath) == NULL) {
> +                send_status(id, errno_to_portable(errno));
> +		xfree(path);
> +		return(NULL);
> +        }
> +        xfree(path);
> +
> +	if (jailpath) {
> +		if (strncmp(resolvedpath, jailpath, strlen(jailpath))) {
> +			send_status(id,SSH2_FX_PERMISSION_DENIED);
> +			return(NULL);
> +		}
> +	}
> +
> +	return(xstrdup(resolvedpath));
> +}
> +
>  void
>  process_init(void)
>  {
> @@ -380,7 +407,10 @@
>  	int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +	if (name == NULL)
> +		return;
> +
>  	pflags = get_int();		/* portable flags */
>  	a = get_attrib();
>  	flags = flags_from_portable(pflags);
> @@ -505,7 +535,10 @@
>  	int ret, status = SSH2_FX_FAILURE;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +        if (name == NULL)
> +                return;
> +
>  	TRACE("%sstat id %d name %s", do_lstat ? "l" : "", id, name);
>  	ret = do_lstat ? lstat(name, &st) : stat(name, &st);
>  	if (ret < 0) {
> @@ -580,7 +613,10 @@
>  	int status = SSH2_FX_OK;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +        if (name == NULL)
> +                return;
> +
>  	a = get_attrib();
>  	TRACE("setstat id %d name %s", id, name);
>  	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
> @@ -646,7 +682,10 @@
>  	u_int32_t id;
>
>  	id = get_int();
> -	path = get_string(NULL);
> +	path = getpath(id);
> +        if (path == NULL)
> +                return;
> +
>  	TRACE("opendir id %d path %s", id, path);
>  	dirp = opendir(path);
>  	if (dirp == NULL) {
> @@ -768,7 +807,10 @@
>  	int ret;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +        if (name == NULL)
> +                return;
> +
>  	TRACE("remove id %d name %s", id, name);
>  	ret = unlink(name);
>  	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
> @@ -785,7 +827,10 @@
>  	int ret, mode, status = SSH2_FX_FAILURE;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +        if (name == NULL)
> +                return;
> +
>  	a = get_attrib();
>  	mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
>  	    a->perm & 0777 : 0777;
> @@ -804,7 +849,10 @@
>  	int ret, status;
>
>  	id = get_int();
> -	name = get_string(NULL);
> +	name = getpath(id);
> +        if (name == NULL)
> +                return;
> +
>  	TRACE("rmdir id %d name %s", id, name);
>  	ret = rmdir(name);
>  	status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
> @@ -820,7 +868,10 @@
>  	char *path;
>
>  	id = get_int();
> -	path = get_string(NULL);
> +	path = getpath(id);
> +        if (path == NULL)
> +                return;
> +
>  	if (path[0] == '\0') {
>  		xfree(path);
>  		path = xstrdup(".");
> @@ -846,8 +897,14 @@
>  	int ret, status = SSH2_FX_FAILURE;
>
>  	id = get_int();
> -	oldpath = get_string(NULL);
> -	newpath = get_string(NULL);
> +	oldpath = getpath(id);
> +        if (oldpath == NULL)
> +                return;
> +
> +	newpath = getpath(id);
> +        if (newpath == NULL)
> +                return;
> +
>  	TRACE("rename id %d old %s new %s", id, oldpath, newpath);
>  	/* fail if 'newpath' exists */
>  	if (stat(newpath, &st) == -1) {
> @@ -867,7 +924,10 @@
>  	char *path;
>
>  	id = get_int();
> -	path = get_string(NULL);
> +	path = getpath(id);
> +        if (path == NULL)
> +                return;
> +
>  	TRACE("readlink id %d path %s", id, path);
>  	if (readlink(path, link, sizeof(link) - 1) == -1)
>  		send_status(id, errno_to_portable(errno));
> @@ -891,8 +951,14 @@
>  	int ret, status = SSH2_FX_FAILURE;
>
>  	id = get_int();
> -	oldpath = get_string(NULL);
> -	newpath = get_string(NULL);
> +	oldpath = getpath(id);
> +        if (oldpath == NULL)
> +                return;
> +
> +	newpath = getpath(id);
> +        if (newpath == NULL)
> +                return;
> +
>  	TRACE("symlink id %d old %s new %s", id, oldpath, newpath);
>  	/* fail if 'newpath' exists */
>  	if (stat(newpath, &st) == -1) {
> @@ -1004,6 +1070,32 @@
>  	}
>  }
>
> +char*
> +jail_init(void)
> +{
> +	char *user_dir, *new_root;
> +
> +	user_dir = getenv("HOME");
> +	if (!user_dir)
> +		fatal("HOME isn't in environment");
> +
> +	new_root = user_dir + 1;
> +
> +	while ((new_root = strchr(new_root, '.')) != NULL) {
> +		new_root--;
> +		if (strncmp(new_root, "/./", 3) == 0) {
> +			*new_root = '\0';
> +			new_root += 2;
> +
> +			return(xstrdup(user_dir));
> +			/*setenv("HOME", new_root, 1);*/
> +			break;
> +		}
> +		new_root += 2;
> +	}
> +	return NULL;
> +}
> +
>  int
>  main(int ac, char **av)
>  {
> @@ -1018,6 +1110,8 @@
>  #ifdef DEBUG_SFTP_SERVER
>  	log_init("sftp-server", SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 0);
>  #endif
> +
> +	jailpath = jail_init();
>
>  	in = dup(STDIN_FILENO);
>  	out = dup(STDOUT_FILENO);
>
>




More information about the openssh-unix-dev mailing list