Re: Alternates to have the look of a CHROOT jail without it actually being a CHROOT
Brought to you by:
xystrus
From: Dan <cd8...@me...> - 2006-09-30 17:53:22
|
Julien, I've found another minor thing that is blocked with the patch. When you try to rename a remote file it says the file doesn't exist. I hope it isn't a massive undertaking to adjust your patch to allow this function but other then that, the patch is still working great. Any chance of you posting the patch somewhere? Looks like you might have a lot of people looking for it. Thanks, Dan Dan wrote: > Julien, > > Just thought you'd like to know. I got your patch and installed it and > it works great. I managed to get everything setup the way I want it > to. Thanks for the help and don't loose that patch as I'm sure there > are a lot of people out there right now that would like to get their > hands on it. As for the size difference, I compiled it with the same > variables and environment as I did before. Same machine and > everything. It doesn't bother me that its got a large file difference. > I was just mentioning it in case (for some strange reason) it was > important for you to debug the code. > > Keep in mind, I did only end up applying the SFTP patch and not the RSSH > patch. > > Thanks a million, > Dan > > > Julien Demoor wrote: > >> Dan, >> >> I found the bug that prevented the creation of files and the attached >> file should correct it. I wrote the patch some time ago and didn't >> install it in a production environment as I had planned, so it was not >> really tested. >> While fixing the bug, I noticed another that makes the patch non >> portable because it uses a GNU extension to POSIX. It should not >> affect you and I will anyway correct it for the next release of OpenSSH. >> >> Concerning the size of sftp-server : mine is 37 KiB, after applying >> the patch, if I let Gentoo's package manager compile it, 105 KiB if I >> do it myself without indicating CFLAGS, etc. >> I guess the difference between 37 K and 78 K is due to different >> platform / compiler version / compiler options. However 550 K sounds >> like a lot and the patch cannot be responsible per se. Did you produce >> the two executables the same way ? >> >> >> Regards, >> >> Julien Demoor >> >> Dan :) wrote: >> >>> Julien, >>> >>> Thanks for the patch, it works almost as expected (I can live with it >>> still saying /home/userdir if it must be that way). However, your >>> patch has also disabled uploading files and creation of remote >>> directories. I confirmed that it is the patch by putting the >>> original sftp-server back and it worked there. I have included the >>> Filezilla log to show you what it is doing. I also noticed that the >>> original sftp-server is 78076 bytes and your new one is 550834 >>> bytes. I don't know if that helps or not but I thought I should tell >>> you in case it does. >>> >>> Thanks for the help. >>> Dan >>> >>> >>> Status: Connecting to core-out.home:22 ... >>> Status: Connected with core-out.home:22, initializing SFTP >>> connection... >>> Command: CONNECT cd83sftp@core-out.home:22 >>> Response: Remote working directory is /home/cd83sftp >>> Status: Connected >>> Status: Retrieving directory listing... >>> Command: PWD >>> Response: Remote directory is /home/cd83sftp >>> Command: LIST >>> Response: Sucessfully received 23 items >>> Status: Directory listing successful >>> Command: CD /home/cd83sftp/ >>> Response: Remote working directory is now /home >>> Command: MKD test >>> Response: mkdir /home/cd83sftp/test: no such file or directory >>> Status: Retrieving directory listing... >>> Command: LIST >>> Response: Sucessfully received 23 items >>> Status: Directory listing successful >>> Status: Starting upload of C:\Documents and >>> Settings\Daniel\Desktop\testfile.txt >>> Command: PUT testfile.txt C:\Documents and >>> Settings\Daniel\Desktop\testfile.txt FALSE >>> Response: /home/cd83sftp/testfile.txt: no such file or directory >>> Error: Upload failed >>> >>> >>> >> ------------------------------------------------------------------------ >> >> --- openssh-4.3p2/sftp-server.c 2006-06-24 19:23:35.000000000 +0100 >> +++ sftp-server.c 2006-09-25 11:02:08.000000000 +0100 >> @@ -41,6 +41,14 @@ >> /* Version of client */ >> int version; >> >> +/* SFTP Restricted Access Patch >> + * Points to the full path to which the user is restricted. >> + * */ >> +char *restricted_path; >> + >> +static int in_path(const char *fname); >> +static int new_file_in_path(const char *fname); >> + >> /* portable attributes, etc. */ >> >> typedef struct Stat Stat; >> @@ -383,7 +391,13 @@ >> flags = flags_from_portable(pflags); >> mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; >> TRACE("open id %u name %s flags %d mode 0%o", id, name, pflags, mode); >> - fd = open(name, flags, mode); >> + if(in_path(name)){ >> + fd = open(name, flags, mode); >> + } else if(new_file_in_path(name)) { >> + fd = open(name, flags, mode); >> + } else { >> + fd = -1; >> + } >> if (fd < 0) { >> status = errno_to_portable(errno); >> } else { >> @@ -504,7 +518,11 @@ >> id = get_int(); >> name = get_string(NULL); >> TRACE("%sstat id %u name %s", do_lstat ? "l" : "", id, name); >> - ret = do_lstat ? lstat(name, &st) : stat(name, &st); >> + if(in_path(name)) { >> + ret = do_lstat ? lstat(name, &st) : stat(name, &st); >> + } else { >> + ret = -1; >> + } >> if (ret < 0) { >> status = errno_to_portable(errno); >> } else { >> @@ -579,25 +597,29 @@ >> name = get_string(NULL); >> a = get_attrib(); >> TRACE("setstat id %u name %s", id, name); >> - if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { >> - ret = truncate(name, a->size); >> - if (ret == -1) >> - status = errno_to_portable(errno); >> - } >> - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { >> - ret = chmod(name, a->perm & 0777); >> - if (ret == -1) >> - status = errno_to_portable(errno); >> - } >> - if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { >> - ret = utimes(name, attrib_to_tv(a)); >> - if (ret == -1) >> - status = errno_to_portable(errno); >> - } >> - if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { >> - ret = chown(name, a->uid, a->gid); >> - if (ret == -1) >> - status = errno_to_portable(errno); >> + if(in_path(name)){ >> + if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { >> + ret = truncate(name, a->size); >> + if (ret == -1) >> + status = errno_to_portable(errno); >> + } >> + if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { >> + ret = chmod(name, a->perm & 0777); >> + if (ret == -1) >> + status = errno_to_portable(errno); >> + } >> + if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { >> + ret = utimes(name, attrib_to_tv(a)); >> + if (ret == -1) >> + status = errno_to_portable(errno); >> + } >> + if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { >> + ret = chown(name, a->uid, a->gid); >> + if (ret == -1) >> + status = errno_to_portable(errno); >> + } >> + } else { >> + status = errno_to_portable(errno); >> } >> send_status(id, status); >> xfree(name); >> @@ -620,6 +642,8 @@ >> name = handle_to_name(handle); >> if (fd < 0 || name == NULL) { >> status = SSH2_FX_FAILURE; >> + } else if (!in_path(name)) { >> + status = errno_to_portable(errno); >> } else { >> if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { >> ret = ftruncate(fd, a->size); >> @@ -655,6 +679,7 @@ >> } >> } >> send_status(id, status); >> + xfree(name); >> } >> >> static void >> @@ -668,7 +693,11 @@ >> id = get_int(); >> path = get_string(NULL); >> TRACE("opendir id %u path %s", id, path); >> - dirp = opendir(path); >> + if(in_path(path)){ >> + dirp = opendir(path); >> + } else { >> + dirp = NULL; >> + } >> if (dirp == NULL) { >> status = errno_to_portable(errno); >> } else { >> @@ -702,6 +731,8 @@ >> path = handle_to_name(handle); >> if (dirp == NULL || path == NULL) { >> send_status(id, SSH2_FX_FAILURE); >> + } else if (!in_path(path)) { >> + send_status(id, errno_to_portable(errno)); >> } else { >> struct stat st; >> char pathname[1024]; >> @@ -752,7 +783,11 @@ >> id = get_int(); >> name = get_string(NULL); >> TRACE("remove id %u name %s", id, name); >> - ret = unlink(name); >> + if(in_path(name)){ >> + ret = unlink(name); >> + } else { >> + ret = -1; >> + } >> status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; >> send_status(id, status); >> xfree(name); >> @@ -772,7 +807,11 @@ >> mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? >> a->perm & 0777 : 0777; >> TRACE("mkdir id %u name %s mode 0%o", id, name, mode); >> - ret = mkdir(name, mode); >> + if(new_file_in_path(name)){ >> + ret = mkdir(name, mode); >> + } else { >> + ret = -1; >> + } >> status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; >> send_status(id, status); >> xfree(name); >> @@ -788,7 +827,11 @@ >> id = get_int(); >> name = get_string(NULL); >> TRACE("rmdir id %u name %s", id, name); >> - ret = rmdir(name); >> + if(in_path(name)){ >> + ret = rmdir(name); >> + } else { >> + ret = -1; >> + } >> status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; >> send_status(id, status); >> xfree(name); >> @@ -810,11 +853,13 @@ >> TRACE("realpath id %u path %s", id, path); >> if (realpath(path, resolvedname) == NULL) { >> send_status(id, errno_to_portable(errno)); >> - } else { >> + } else if (in_path(resolvedname)) { >> Stat s; >> attrib_clear(&s.attrib); >> s.name = s.long_name = resolvedname; >> send_names(id, 1, &s); >> + } else { >> + send_status(id, errno_to_portable(errno)); >> } >> xfree(path); >> } >> @@ -832,44 +877,49 @@ >> newpath = get_string(NULL); >> TRACE("rename id %u old %s new %s", id, oldpath, newpath); >> status = SSH2_FX_FAILURE; >> - if (lstat(oldpath, &sb) == -1) >> - status = errno_to_portable(errno); >> - else if (S_ISREG(sb.st_mode)) { >> - /* Race-free rename of regular files */ >> - if (link(oldpath, newpath) == -1) { >> - if (errno == EOPNOTSUPP >> + if (in_path(oldpath) && in_path(newpath)){ >> + if (lstat(oldpath, &sb) == -1) >> + status = errno_to_portable(errno); >> + else if (S_ISREG(sb.st_mode)) { >> + /* Race-free rename of regular files */ >> + if (link(oldpath, newpath) == -1) { >> + if (errno == EOPNOTSUPP >> #ifdef LINK_OPNOTSUPP_ERRNO >> - || errno == LINK_OPNOTSUPP_ERRNO >> + || errno == LINK_OPNOTSUPP_ERRNO >> #endif >> - ) { >> - struct stat st; >> + ) { >> + struct stat st; >> >> - /* >> - * fs doesn't support links, so fall back to >> - * stat+rename. This is racy. >> - */ >> - if (stat(newpath, &st) == -1) { >> - if (rename(oldpath, newpath) == -1) >> - status = >> - errno_to_portable(errno); >> - else >> - status = SSH2_FX_OK; >> + /* >> + * fs doesn't support links, so fall back to >> + * stat+rename. This is racy. >> + */ >> + if (stat(newpath, &st) == -1) { >> + if (rename(oldpath, newpath) == -1) >> + status = >> + errno_to_portable(errno); >> + else >> + status = SSH2_FX_OK; >> + } >> + } else { >> + status = errno_to_portable(errno); >> } >> - } else { >> + } else if (unlink(oldpath) == -1) { >> status = errno_to_portable(errno); >> - } >> - } else if (unlink(oldpath) == -1) { >> - status = errno_to_portable(errno); >> - /* clean spare link */ >> - unlink(newpath); >> - } else >> - status = SSH2_FX_OK; >> - } else if (stat(newpath, &sb) == -1) { >> - if (rename(oldpath, newpath) == -1) >> - status = errno_to_portable(errno); >> - else >> - status = SSH2_FX_OK; >> + /* clean spare link */ >> + unlink(newpath); >> + } else >> + status = SSH2_FX_OK; >> + } else if (stat(newpath, &sb) == -1) { >> + if (rename(oldpath, newpath) == -1) >> + status = errno_to_portable(errno); >> + else >> + status = SSH2_FX_OK; >> + } >> + } else { /* if (in_path(... */ >> + status = errno_to_portable(errno); >> } >> + >> send_status(id, status); >> xfree(oldpath); >> xfree(newpath); >> @@ -886,15 +936,19 @@ >> id = get_int(); >> path = get_string(NULL); >> TRACE("readlink id %u path %s", id, path); >> - if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) >> + if(in_path(path)){ >> + if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) >> + send_status(id, errno_to_portable(errno)); >> + else { >> + Stat s; >> + >> + buf[len] = '\0'; >> + attrib_clear(&s.attrib); >> + s.name = s.long_name = buf; >> + send_names(id, 1, &s); >> + } >> + } else { >> send_status(id, errno_to_portable(errno)); >> - else { >> - Stat s; >> - >> - buf[len] = '\0'; >> - attrib_clear(&s.attrib); >> - s.name = s.long_name = buf; >> - send_names(id, 1, &s); >> } >> xfree(path); >> } >> @@ -911,7 +965,11 @@ >> newpath = get_string(NULL); >> TRACE("symlink id %u old %s new %s", id, oldpath, newpath); >> /* this will fail if 'newpath' exists */ >> - ret = symlink(oldpath, newpath); >> + if(in_path(oldpath) && in_path(newpath)){ >> + ret = symlink(oldpath, newpath); >> + } else { >> + ret = -1; >> + } >> status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; >> send_status(id, status); >> xfree(oldpath); >> @@ -1030,16 +1088,87 @@ >> buffer_consume(&iqueue, msg_len - consumed); >> } >> >> +static int >> +in_path(const char *fname) >> +{ >> + /* SFTP Restricted Access Patch version 1.0 - written by Julien Demoor <julien at jdemoor dot com> >> + * The OpenSSH license terms apply. >> + * sftp-server takes an argument (typically from scponly or rssh) to restrict users in a directory. >> + * >> + * Returns 1 if the file/directory specified by fname is a descendent of the user's allowed directory. >> + * Returns 0 otherwise. It is the responsibility of the caller to send the appropriate error message >> + * to the client. >> + * Always return 1 if there is no restriction. >> + * */ >> + >> + char *real_name = NULL; >> + >> + if(restricted_path == NULL) >> + return 1; >> + >> + real_name = realpath(fname, real_name); >> + if (!real_name){ >> + return 0; >> + } >> + if(strncmp(real_name,restricted_path,strlen(restricted_path)) == 0){ >> + free(real_name); >> + return 1; >> + } else { >> + free(real_name); >> + errno = EACCES; >> + return 0; >> + } >> + >> +} >> + >> +static int >> +new_file_in_path(const char *fname) >> +{ >> + /* This function checks the restriction against names that do not exist yet. */ >> + >> + char *i = NULL, *lpos = NULL, *real_name = NULL; >> + >> + for(i = fname; *i != '\0'; i++){ >> + if (*i == '/') >> + lpos = i; >> + } >> + if(lpos == NULL){ >> + /* No slash, no trick. We just assume the directory we're in is already checked. */ >> + return 1; >> + } else { >> + *lpos = '\0'; >> + if(!(real_name = (realpath(fname, real_name)))){ >> + *lpos = '/'; >> + errno = EACCES; >> + return 0; >> + } else { >> + if(strncmp(real_name,restricted_path,strlen(restricted_path)) == 0){ >> + free(real_name); >> + *lpos = '/'; >> + return 1; >> + } else { >> + free(real_name); >> + *lpos = '/'; >> + errno = EACCES; >> + return 0; >> + } >> + } >> + } >> +} >> +/* End patch. */ >> + >> int >> main(int ac, char **av) >> { >> fd_set *rset, *wset; >> int in, out, max; >> ssize_t len, olen, set_size; >> + int i; >> + char *temp; >> >> /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ >> sanitise_stdfd(); >> - >> + >> /* XXX should use getopt */ >> >> __progname = ssh_get_progname(av[0]); >> @@ -1056,7 +1185,28 @@ >> setmode(in, O_BINARY); >> setmode(out, O_BINARY); >> #endif >> + >> + /* SFTP Restricted Access Patch */ >> + restricted_path = NULL; >> + if(ac >= 3){ >> + for(i=1;i<ac;i++){ >> + if(memcmp(av[i],"--rpath",8)==0 && ++i <= ac){ >> + restricted_path = av[i]; >> + break; >> + } >> + } >> + if(restricted_path != NULL) { >> + temp = xmalloc(384); >> + restricted_path = realpath(restricted_path, temp); >> + if(restricted_path == NULL){ >> + /* Could not get the real path, we log and exit. */ >> + fatal("Supplied argument (--rpath) is invalid. Exiting."); >> + } >> + } >> + } >> + /* End patch */ >> >> + >> max = 0; >> if (in > max) >> max = in; >> >> ------------------------------------------------------------------------ >> >> No virus found in this incoming message. >> Checked by AVG Free Edition. >> Version: 7.1.405 / Virus Database: 268.12.8/455 - Release Date: 9/22/2006 >> >> > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys -- and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > rssh-discuss mailing list > rss...@li... > https://lists.sourceforge.net/lists/listinfo/rssh-discuss > > |