An(other?) approach to chrooting sshd under OpenBSD
| Table of contents |
Introduction and acknowledgments
I started my quest because I needed a way to host a directory that would allow 2 different groups
of people to share files securely. One group is in the process of turning off Windows file sharing
visible outside their subnet, and requested we run an sftp server, presumably because it simplifies
their firewall ruleset by letting them do some equivalent of 'pass out all on intf_x keep state'. In
any case, neither group has any need to poke around the rest of the machine, and I didn't want to have
to set up a separate machine for them.
I began by doing the usual searching with Google, monkey.org's search of OpenBSD archives, and FreeBSD's search of their mailing lists. I didn't find quite what I wanted, so I posted a question to comp.unix.bsd.openbsd.misc. I got a couple of replies, which pointed me toward http://chrootssh.sourceforge.net and http://www.sublimation.org/scponly/. Both of these came close to what I wanted, but neither actually worked in my situation.
What is chroot()?
OK, here we go with the newbies guide, at least for a minute. chroot stands for change root directory,
and that's what it does, for the user or process affected. There's both a C function (see man 2 chroot)
and a command/program (see man 8 chroot) which do the same thing, depending on what you need. If you're
wondering why I wrote command/program you'll see in a minute.
When you get chrooted, you can't see beyond the directory that you're chrooted into. Period. Actually there are some tricks for breaking out (see the links at the bottom of http://chrootssh.sourceforge.net/docs/chrootedsftp.html) but I'm being naive for the sake of this discussion. It may seem an odd analogy, but I'm about to get a new kitten. For several weeks, that kitten won't be allowed outside my apartment. Everything it eats, drinks, sees or does will be indoors. The apartment will become its world for that time, so that it will consider it home when I do let it out. I have to provide everything it will need. It will be chrooted to my apartment. It can look out the windows, which is more than someone chrooted into a directory can do. Think of it as an exercise in perspective.
It wasn't an accident that I wrote command/program above. If you're new to the unix world, you may not
realize yet that when you type ls to list a directory or
cp to copy a file,
you're actually running programs named ls and cp. Most of the things we take for granted are actually
separate programs. For a user to log into a chrooted directory with some GUI sftp client and see a list
of files, there has to be an ls available. Which means there has to be a copy of ls inside the chrooted
directory, because the user can't see or run the one outside. The same is true of cp, cat, mv, rm, mkdir,
rmdir and others. This implies a responsibility to provide what they need, but it also gives you the power
of not letting them at things they might cause mischief with like su, chmod, or a C compiler.
The way this modification to sshd works is by looking for the string "/./" in what is stored as being the user's home directory. It took me a while to figure this out from what I was reading, but there is never actually a directory with /./ in it. That's only a switch to tell sshd where to split the path and do the chroot. If it doesn't find it, it doesn't chroot. This is completely transparent to normal users - if there isn't /./ in your home directory you don't get chrooted.
![]() chrooted on right |
In my case, I put the chrooted directory on a separate physical drive, mounted as /drv2. My chrooted parent directory is called chrooted, and sits in the root of /drv2. My user directory I installed inside that is called r25.
The home directory for the r25 user is specified as
When the r25 user logs in, they're inside
This is a convenience to all concerned. Remember that they need to have all their programs, libraries,
and a few other things within the space that they can see. If the chroot locked them into
This is also a convenience to the administrator, since adding more chrooted accounts just means running adduser again to create more accounts with their home directories inside "/drv2/chrooted/." Since none of them can change anything in that shared area, (or in each other's) you don't have to re-create the whole thing for each one. Even better, if you've got a user who's being a problem, you can just move their home directory inside the chrooted area and change their official home directory to have the /./. They'll at least get the idea that they've been warned. (Spiffy graphics courtesy of Total Commander and IrfanView) |
Since the string "/./" always has the same length of 3, what the patch is doing is chrooting to the directory before that string, then setting the home directory to what comes after it. If I keep looking at these I might actually learn how to manipulate strings in C.
Installing
Exit newbie mode. If you're installing a chrooted OpenSSH for OpenBSD, which this is all about,
get the latest version of OpenSSH that is specifically designed for OpenBSD. OpenSSH was written under
OpenBSD, and when they made it portable/generic for other operating systems they somehow got it where
it doesn't work quite the same way. At least it's got extra stuff you don't need. Go to
http://www.openssh.org/openbsd.html to get a pure version.
Put it right into /usr/src/usr.bin/. If you've done this before, or you're overly
confident or in a terrible hurry, just delete the ssh directory without backing it up first.
Otherwise do something like tar -csv old_ssh.tar ssh/*.
Then delete the ssh directory with something like
rm -R ssh. If you
really got the OpenBSD version it will make a new ssh directory when you extract it. It will also
install everything in the proper places when you do a make install. The generic version won't.
So, you've got the new tgz file in /usr/src/usr.bin and you're removed the old /usr/src/usr.bin/ssh
directory. Now you're ready to do something like (I still like the old 2-step process):
gunzip openssh*.tgz then
tar -xvf openssh-3.6.1.tar (Substitute your exact version here - tar doesn't like wildcards)
Now you have an ssh directory again. CD into it. The file you need to modify is session.c and it's a
good idea to make a copy of it first by doing something like
cp session.c session_backup.c
Have patience, I'm from the old school.
session.c is what you need to modify and how you do it is up to you. I'm not fond of patches, and I wouldn't have spent most of last weekend figuring this out if the patch had worked. A patch is potentially a quick way of making the changes you need to make if it works. I present a patch later on that you can copy and paste into a file to apply if you want. This is a relatively simple change you need to make. You're just adding a function and inserting one line into an existing one to call it. The new function can be placed almost anywhere before the existing one (as long as you don't put it inside another function).
Here's the new function. You can copy and paste this:
/* I've isolated the part that does the chroot and put it in its own function */
void
do_chroot(struct passwd *pw){
char *user_dir;
char *new_root;
user_dir = xstrdup(pw->pw_dir);
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;
if(chroot(user_dir) != 0)
fatal("Couldn't chroot to user directory %s", user_dir);
pw->pw_dir = new_root;
break;
}
new_root += 2;
}
} /* do_chroot */
That should go before the function do_setusercontext. (You can search for do_setusercontext and put
your new code in the blank lines above that.)
do_chroot(pw); /* insertion of this is the only change in the original code */
/* Set login name, uid, gid, and groups. */
void
do_setusercontext(struct passwd *pw)
{
do_chroot(pw); /* insertion of this is the only change in the original code */
if (getuid() == 0 || geteuid() == 0) {
#ifdef HAVE_LOGIN_CAP
That's it: that's all there is to this patch. Simple, huh? I thought so after I'd spent hours poking around in a pre-patched version that wasn't working trying to figure out what the problem was and then saw the bare patch. In the pre-patched version the code for the patch ends up inside an area that's never even compiled due to some #ifdefs checking something that's always true in OpenBSD but apparently isn't in Linux where the patch was written. I kept sticking in printf statements to have some idea where the program flow was going wrong, but I was never seeing anything. The #ifdefs aren't just a branch in the code, they're an instruction to the preprocessor to leave out the section of code inside under certain conditions, so the patch and my printfs were never getting compiled into the executable at all.
How you modify the code is your business. Being sometimes not much of a purist I cheated. I FTPed session.c to a Windows machine as ASCII, modified it, and FTPed it back as ASCII. I don't have X running on anything convenient and this is a situation that lends itself well to copying and pasting. You could also isolate the new function into a text file by itself, then open session.c in an editor, put the cursor where the function goes, and read the block in. Ctrl-K R will read a block in Joe. vi? Emacs? I never use them.
So now you've got your modified session.c in place, you're in the /usr/src/usr.bin/ssh directory and you're ready to
build. The basic commands to type are:
make obj
make cleandir
make depend
make
And then you pause.
If you haven't seen any errors up to this point, good. The only likely errors would be in the
make step, and they'd most likely happen because
something didn't go right in modifying the code. If you get errors compiling session.c you should
have a line number showing after it stops, so look at the code and figure out what's wrong.
I did get a warning some times I compiled that has to do with not having a smartcard, something related to
"scard" but that's it. I did most of my work on this at home on an Athlon XP 1800 running OpenBSD 3.3,
but my target production machine is an old 200 MHZ Pentium 1 running OpenBSD 3.1. I just tried to reproduce the warning for the sake of
documenting it here at home, but I couldn't find it. If you really want to scrutinize your output from the various make
steps, use tee. Something like make | tee make_output.txt works well.
Most of the time it either flies by too fast to read, or it goes so slowly you don't pay attention.
We're also paused here because the next step is going to replace your existing ssh daemon. If you're logged on remotely
via ssh, this is the time to log out and walk to the machine for the next couple of steps. If that's absolutely impossible,
like if you're installing from miles away, you can turn on telnet temporarily and use that to connect. Just do
/usr/libexec/telnetd -debug to start it. I just tried it and the daemon
seemed to die by itself when I disconnected.
Whatever method you use to talk to your box independantly of ssh, the process is about the same. You want to kill off any
sshd instances that are around. I usually start by running top, and doing a k then entering the appropriate process number
which I read from the screen as it's bouncing around. Most likely there will be more than one instance and you'll need to
get them one at a time. When you don't see any more, do a cat
/var/run/sshd.pid, then kill -9 (whatever process number you saw)
. You'll probably see "No such process", and that's good. The ssh daemon is
one of those, like Apache, that spawns children to always have some available for an incoming connection. The
/var/run/sshd.pid file only contains the process number of the last one that was started. It gets overwritten every time
a new one starts up. When you think you've gotten them all, try (as root):
rm /usr/sbin/sshd. If you don't get a prompt back like
"override r-xr-xr-x root/bin for sshd?" you're all set, sshd is shut down. If you do get the prompt, hit n and
keep looking for more instances.
When you don't get any more resistance to deleting sshd, it's gone and you're ready to install the new one. Do a
cd /usr/src/usr.bin/ssh then
make install. It should only take a few seconds because you're just
copying some files into place. Restart sshd by typing
/usr/sbin/sshd. You should now be able to connect normally via ssh, so
test that then either log out of your telnet connection or go back to your more comfortable seat.
Building the jail
We couldn't do this before we rebuilt sshd, because one of the files we need to copy into it, sftp-server, has also just
been rebuilt. Using a script to build a jail is a concept I got from
http://www.sublimation.org/scponly/. I couldn't use their approach
because I need true sftp, not scp. I've ended up with both, and that's OK. Building a jail with a script works well when
you're trying to tell someone how to do it, and in my case where I was practicing on one machine to do an install on a
different one it worked well. I fiddled with this script until it did what I wanted at home, then when I ran it at work
there were no surprises. As I've mentioned, it was written under OpenBSD 3.3 and worked fine under 3.1.
Before you can use the script, you need to decide where you're going to put your new jail. The filesystem can't be
mounted nodev. I think in most systems there's at least one filesystem that's mounted nodev but / can't be. The way to
check is to
cat /etc/fstab You should see something like:
george# cat /etc/fstab /dev/sd0a / ffs rw 1 1 /dev/sd0d /usr ffs rw,nodev 1 2In this case, I can't put the jail on /dev/sd0d Also in this case that was no big deal because I could put it elsewhere (I have a RAID 5 array that I mount manually, so it's not in fstab). Supposedly you can take the nodev out of fstab for that filesystem and either unmount and remount it or reboot without any great penalty, but I didn't need to.
If, when you start testing or using your chroot, you see some error like this:
/bin/sh: No controlling tty (open /dev/tty: Device not configured) /bin/sh: warning: won't have full job controlThat's the most likely reason. Another possibilty is that something went wrong with making the /dev/tty device inside the jail, but that's less likely. I think I've also seen this if I've tried to move an existing jail. You can't do that, you need to make a new one and move the user directories into it.
OK, here's my makejail.sh script. Create the directory that's going to become the jail where you want it, put the
makejail.sh script inside it, cd into it, then, as root, run the script. Copy this off your web browser screen and paste it
into a text file to create your own copy. It doesn't have the necessary magic to be executable by itself, so you'll have
to run it by doing sh makejail.sh
mkdir bin cp `whereis ls` bin cp `whereis sh` bin cp `whereis cp` bin cp `whereis mkdir` bin cp `whereis mv` bin cp `whereis rm` bin cp `whereis rmdir` bin cp `whereis cat` bin cp `whereis groups` bin mkdir usr mkdir usr/lib cp /usr/lib/libutil.so* usr/lib cp /usr/lib/libz.so* usr/lib cp /usr/lib/libcrypto.so* usr/lib cp /usr/lib/libc.so* usr/lib mkdir usr/libexec cp /usr/libexec/sftp-server usr/libexec cp /usr/libexec/ld.so usr/libexec #chmod +s usr/libexec/sftp-server mkdir usr/bin cp `whereis id` usr/bin mkdir etc cp /etc/group etc mkdir dev cd dev mknod zero c 13 12 mknod null c 13 2 mknod tty c 1 0 chmod 666 * cd .. |
Notes about the script
I've tried to make it as version-independant as possible in a couple of ways. I'm using the whereis command to find executables,
rather than expecting them to be at certain locations. By putting the whereis in backticks (upper left corner of the keyboard)
I'm feeding the location found by whereis into cp. I've also not including a version number when copying libraries with lines
like "cp /usr/lib/libutil.so*". On my machine, at present, there's only one version of each library anyway. After an
upgrade things could get more complicated and there would end up being more junk in the jail lib directories. The line
"#chmod +s usr/libexec/sftp-server" is commented out, because I found conflicting advice. One source says the
sftp-server should be setuid root, another says there shouldn't be any setuid root programs in the jail. It's working
without doing the setuid, so it's probably better this way from a security standpoint. I think the setuid was only intended
to give access to port numbers this low. I just checked in Top with my user connected using an sftp client, and I see
sftp-server, sshd and sh all running as that user.
It's best to move the makejail.sh script out of the jail after you've run it so users don't find it.
Testing the jail
So, if you didn't see any errors running the makejail.sh script, you're ready to test the chroot. Become root, whether by
su or logging on as root. This is not testing the ability of sshd to chroot, it's testing the integrity of the chroot jail
itself. Change the jail path here as appropriate when you type it:
chroot /drv2/chrooted /bin/sh
You should find yourself inside the
jail. Do a cd / and then ls.
You should only see the outer directories in your jail: bin, dev, etc and usr. You should not have gotten the error about no
controlling tty as discussed above under the nodev filesystem. Try a command you know you didn't include, like
su. You should get an error. Try breaking out, but don't bother trying
very long. When you get bored type exit to return to your original process.
Adding users
Now it's time to add some user accounts inside this jail. You can do this with adduser from the command line, and if you're
going to be adding a lot of them you probably want to write a script to automate it by doing them all at once. I'm not going to
discuss the command line options here. See man adduser for those if you
want to use it. I used it in interactive mode.
Before you do that, you should make a change in /etc/adduser.conf
Find this section:
# default HOME directory ("/home")
# home = "/home"
home = "/drv2/chrooted/."
Comment out the default home defined and add your own for the chrooted users on another line, as above. The new path
should end with a period as above. When adduser makes a new directory it will append / and the new username. When you want
to go back to adding normal users, comment that line out and uncomment the original line.
When that's done, type adduser. The script will prompt you through, and the session will look something like what's below. When in doubt about something, it's usually safe to accept the default by hitting enter.
leto# adduser Use option ``-silent'' if you don't want to see all warnings and questions. Reading /etc/shells Check /etc/master.passwd Check /etc/group Ok, let's go. Don't worry about mistakes. I will give you the chance later to correct any input. Enter username [a-z0-9_-]: fred Enter full name []: fred chrooted Enter shell csh ksh nologin scponlyc sh tcsh [sh]: Uid [1005]: Login group fred [fred]: Login group is ``fred''. Invite fred into other groups: guest no [no]: Enter password []: Enter password again []: Name: fred Password: **** Fullname: fred chrooted Uid: 1005 Gid: 1005 (fred) Groups: fred HOME: /drv2/chrooted/./fred Shell: /bin/sh OK? (y/n) [y]: y |
rmuser fred and hit y at the confirmation prompts.
Test logging in as the user
Start an ssh client and try connecting to the machine where you built the jail, logging in with the account you just made.
You should find yourself inside the same jail you were in before when you tested chroot, except you'll start out inside the
new user's directory that was just created by adduser.
$ pwd /r25 $ cd / $ ls bin dev etc r25 usr $ |
|
Next, you should try connecting with an sftp client (or do sftp <machine name> from another Unix box if you've got a second one). I was lazy and used the Windows client we expect to use at work. This is from http://www.ssh.com and is the version that's free for non-commercial use (I work for a state university). This is the root directory as the chrooted user will see it, and shows exactly the same things we can see from a command line when we do an ls after doing cd /.
|
|
|
This is a Windows SCP client called WinSCP2, also freeware and with a homepage at http://winscp.vse.cz/eng/
I didn't care about having SCP work, but being compatible with it could come in handy. It worked before I got sftp working, and even better, it gave helpful error messages before it was working that told me what was missing from my jail. These hints are why there's /etc/group, /bin/groups and /usr/bin/id in my jail. I don't know if they're needed other than for SCP. SCP is similar to sftp, but not exactly the same thing. See man scp and man sftp for details. It works, and it got chrooted, that's what matters to me.
|
Are you done? Not yet.
Think about what we've done here. We've added a user and chrooted them when they're connected using ssh, sftp and scp. What about other methods of connecting? The question is what other methods you've got enabled. They can connect via telnet or traditional ftp and look around all they want, if you're running those daemons. You shouldn't be running telnet period, because of the plaintext passwords used for login. Turn off the daemon and get your users to run ssh instead. Freeware clients are available so there's no good excuse for not using it (except possibly that it's not built into Windows).
Traditional FTP is another matter. I haven't seen anything in sftp that's going to replace anonymous FTP for downloading files from some support directory at a company where you don't have an account. I still prefer getting drivers that way over having to use HTTP, although using wget helps. I've also noticed that sftp is significantly slower than FTP when there are slow machines involved because of the CPU overhead for encrypting all that data. Sometimes you don't care about encryption if the material isn't of a sensitive nature. Again, wget comes to the rescue. I just put what I want to download into a subdirectory that Apache can see and download via HTTP. wget has an amazing ability to get the data through, even when your ISP disconnects in the middle of the night and your system has to redial.
For restricting FTP users, there are about 2 options. You can put their usernames in /etc/ftpusers to prevent them from logging in that way at all, or you can put their usernames in /etc/ftpchroot and they'll get chrooted to their home directories when they log in. And yes, of course, FTP also uses unencrypted passwords.
For more options, and for restricting other login possibilities, see man hosts.allow.
File and directory permissions
Actually, the permissions on files and directories ended up pretty much the way I wanted them to, and that was more by accident than by design. I've looked carefully in all the subdirectories on both machines, and I haven't found anything I want to change.
Take a look for yourself:
total 6 drwxr-xr-x 2 root wheel 512 Aug 18 09:06 bin drwxr-xr-x 2 root wheel 512 Aug 18 09:06 dev drwxr-xr-x 2 root wheel 512 Aug 18 09:06 etc drwxr-xr-x 2 r25 r25 512 Aug 18 09:59 r25 drwxr-xr-x 5 root wheel 512 Aug 18 09:06 usr ./bin: total 1049 -r-xr-xr-x 1 root wheel 53248 Aug 18 09:06 cat -r-xr-xr-x 1 root wheel 73728 Aug 18 09:06 cp -r-xr-xr-x 1 root wheel 116 Aug 18 09:06 groups -r-xr-xr-x 1 root wheel 167936 Aug 18 09:06 ls -r-xr-xr-x 1 root wheel 53248 Aug 18 09:06 mkdir -r-xr-xr-x 1 root wheel 159744 Aug 18 09:06 mv -r-xr-xr-x 1 root wheel 163840 Aug 18 09:06 rm -r-xr-xr-x 1 root wheel 49152 Aug 18 09:06 rmdir -r-xr-xr-x 1 root wheel 307200 Aug 18 09:06 sh ./dev: total 0 crw-rw-rw- 1 root wheel 13, 2 Aug 18 09:06 null crw-rw-rw- 1 root wheel 1, 0 Aug 18 09:06 tty crw-rw-rw- 1 root wheel 13, 12 Aug 18 09:06 zero ./etc: total 1 -rw-r--r-- 1 root wheel 433 Aug 18 09:06 group ./r25: total 2 -rw-r--r-- 1 r25 r25 131 Aug 18 10:05 .profile -rw-r--r-- 1 root r25 45 Aug 18 10:06 test.txt ./usr: total 3 drwxr-xr-x 2 root wheel 512 Aug 18 09:06 bin drwxr-xr-x 2 root wheel 512 Aug 18 09:06 lib drwxr-xr-x 2 root wheel 512 Aug 18 09:06 libexec ./usr/bin: total 12 -r-xr-xr-x 1 root wheel 12288 Aug 18 09:06 id ./usr/lib: total 1484 -r--r--r-- 1 root wheel 598961 Aug 18 09:06 libc.so.28.3 -r--r--r-- 1 root wheel 801706 Aug 18 09:06 libcrypto.so.5.1 -r--r--r-- 1 root wheel 38246 Aug 18 09:06 libutil.so.7.1 -r--r--r-- 1 root wheel 55094 Aug 18 09:06 libz.so.1.4 ./usr/libexec: total 88 -r-xr-xr-x 1 root wheel 61440 Aug 18 09:06 ld.so -r-xr-xr-x 1 root wheel 28672 Aug 18 09:06 sftp-serverA script like this is a sort of automated checklist. I kept finding other things I needed to add to the jail, adding them and testing that the program worked, then adding them to the script. Then I'd test the script by making another jail somewhere else. As I mentioned above (somewhere) this script was intended to be both part of this document, and my means of duplicating my jail on the target machine at work.
It's not an accident that I haven't provided any way for users to change their password. In this context, most of the use will be with GUI clients for sftp as pictured above. There isn't any way for them to change passwords with that interface anyway. Also, this same account will be used on both ends: by the group that's putting files in and by the group that's taking them out. None of this data is of a sensitive nature, and we've had bad experiences before with sharing an account between users when one could change the password and not inform the others.
Adding other programs to the jail
There's not all that much to it, you just copy them in. At least if they're statically linked.
(OK, newbie mode again: When you write a program, you can include all of the code needed to make it run (statically linked), or you can call functions in external libraries (dynamically linked). If you include all the code you make the program bigger. It's more efficient space-wise to call external libraries then to generate redundant code. On the other hand, a program's more portable and often runs faster if it's self-contained. The portability can be not just to a chroot jail, but to another machine maybe running a different version of OpenBSD, or maybe even something like FreeBSD with an emulation mode. You can also generally keep using a statically linked program without recompiling it when you upgrade your operating system by a few versions. That's not important for stuff built into the operating system anyway, but if you program and you've written utilities you use regularly you can just copy them and chmod them to be executable again.)You can find out what programs are statically linked and which are dynamically linked by using ldd:
george# ldd /bin/sh
ldd: /bin/sh: not a dynamic executable
george# ldd /usr/libexec/sftp-server
/usr/libexec/sftp-server:
-lcrypto.9 => /usr/lib/libcrypto.so.9.0 (0x40022000)
-lc.29 => /usr/lib/libc.so.29.0 (0x40102000)
george# ldd /usr/local/bin/tcsh
/usr/local/bin/tcsh:
-ltermlib.9 => /usr/lib/libtermlib.so.9.0 (0x40065000)
-lc.29 => /usr/lib/libc.so.29.0 (0x400a4000)
george#
|
When copying things, I chose to replicate the original paths inside the jail. You might be able to take things from /usr/bin and copy them into /bin in your jail, but doing it this way seemed cleaner somehow.
Other shells
You can use other shells in your jail besides sh, it just takes more work. You need to include any libraries they need for starters. You should specify the alternate shell when you're running adduser, although you can change that later with chsh. I didn't seem to need an /etc/shells file, but if you're using something other than /bin/sh you probably will. Almost certainly adduser will complain unless you have the shell in place and add it to /etc/shells before you add a user that's using it.
Now you're done, at least I am.
A concise set of instructions, for the impatient. These were actually my notes to myself for doing the 2nd install:
1. make the chrooted parent directory where it should be (I'm using /drv2/chrooted) 2. cd /usr/src/usr.bin 3. tar -cvf ssh_removed.tar ssh/* 4. rm -R ssh 5. wget ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/openssh-3.6.1.tgz (or whatever the latest is) 6. gunzip openssh-3.6.1.tgz 7. tar -xvf openssh-3.6.1.tar 8. cd ssh 9. manually make the changes in session.c (or patch?) 10. make obj 11. make cleandir 12. make depend 13. make 14. from a physical console kill the sshd and delete it (/usr/sbin/sshd) 15. cd back to /usr/src/usr.bin/ssh and make install 16. restart the sshd daemon 17. test ssh login as yourself, go back to comfortable seat 18. edit /etc/adduser.conf so default home is "/drv2/chrooted/." (change back later) 19. Add the new chrooted user with adduser 20. cd into /drv2/chrooted 21. copy the makejail.sh script into /drv2/chrooted/, run it and delete it 22. cd into new user's directory 23. correct paths in user's dotfiles to remove non-existant ones 24. test by logging in from ssh as the user 25. test by using an sftp client as the user 26. optionally test by using a scp client (ie WinSCP2) as the user 27. if you want to add more chrooted users, do it now, then change /etc/adduser.conf back 28. remember that this chroot only applies through sshd. Other daemons (ftpd, telnetd) will not chroot them.
A patch, for those that insist on one
Patches are fragile, and they often break when the version of the code being patched changes. This is a patch against session.c in openssh-3.6.1.tgz, the version that's specifically for OpenBSD.
*** session_unmodified.c Wed Mar 5 17:33:43 2003
--- session.c Mon Aug 18 08:54:20 2003
***************
*** 1018,1027 ****
--- 1018,1053 ----
}
}
+ /* I've isolated the part that does the chroot and put it in its own function */
+ void
+ do_chroot(struct passwd *pw){
+ char *user_dir;
+ char *new_root;
+
+ user_dir = xstrdup(pw->pw_dir);
+ 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;
+
+ if(chroot(user_dir) != 0)
+ fatal("Couldn't chroot to user directory %s", user_dir);
+ pw->pw_dir = new_root;
+ break;
+ }
+ new_root += 2;
+ }
+ } /* do_chroot */
+
+
+
/* Set login name, uid, gid, and groups. */
void
do_setusercontext(struct passwd *pw)
{
+ do_chroot(pw); /* insertion of this is the only change in the original code */
if (getuid() == 0 || geteuid() == 0) {
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid,
The End
That's the end of my saga. I hope what I learned and put here will be helpful to someone else. I wish I could put an email address here for contacting me, but really what I've put on this page is about all I know about the subject, and I'm approaching 200 spam emails per day now so I'm not putting my email address in any more places. I am subscribed to the mailing list at http://chrootssh.sourceforge.net with one email account and check that every few days.
Oh, and a thank you to all who helped, both through the mailing list and through comp.unix.bsd.openbsd.misc
Alan Corey
|
|
|