/** * Program to allow telnet access to a chrooted home directory. * (c) 1998 Semiotek Inc (Justin Wells). All rights reserved. * * Permission granted to use and redistribute freely, providing * this notice remains intact. By using or distributing this software * you agree that you are using the software at your own risk, and * that Semiotek Inc. is absolved of any liability relating to harm that * may come to you or your business as a result of using this software. * * USE: This program acts as the users shell according to the real * password file. On login it chroots to the users home directory, * then calls getpwent and grabs a new home directory and shell for * the user. It will chdir to this new directory, and exec the shell * it identifies. It will fail under a bunch of conditions that are * either unexpected, or a sign that things are not working well. * Note that the getpwent after the chroot returns data from the * /etc/passwd file in the chrooted partition. * * INSTALL: compile this program and install it setuid root. it must * be setuid root on most Unix systems in order to perform the chroot. * It will set uid back to the user before it execs their shell. * * BUGS: no log is written out, and the program is easily upset. * errors do go to stdout, but these messages are not always available * when debugging a problem. No independent security audit has been * performed. In fact, the code had never even been read by anyone else. */ #include #include #include #include #include int main(int argc, char **argv) { char *home; char *chroothome; int rc; uid_t uid = getuid(); struct passwd *pw; /* i can't imagine why root would log in chrooted, so prevent it */ if (0 == uid) { printf("FAILED: cannot run as root\n"); exit(1); } FILE* log = fopen("/var/log/securelogin.log", "a"); int i; fprintf(log, "uid %d: Args:", uid); for (i = 0; i < argc; i++) { fprintf(log," '%s'", argv[i]); } fprintf(log,"\n"); fclose(log); /* get the password info */ pw = getpwuid(uid); if (NULL == pw) { printf("FAILED: no such user id or cannot get passwd entry\n"); exit(1); } /* switch to the secured area, and try to chroot */ home = pw->pw_dir; if (NULL == home) { printf("FAILED: could not locate home area\n"); exit(1); } if (chdir(home)) { printf("FAILED: could not to chdir before chroot to %s (does it exist?)\n", home); exit(2); } if (chroot(home)) { printf("FAILED: could not to chroot to %s (are we suid?)\n", home); exit(2); } /* get the inside chroot home */ pw = getpwuid(uid); if (NULL == pw) { printf("FAILED: cannot get password info in chroot'd /etc/passwd\n"); exit(1); } chroothome = pw->pw_dir; if (NULL == chroothome) { printf("FAILED: could not locate home area in chroot'd /etc/passwd\n"); exit(1); } if (chdir(chroothome)) { printf("FAILED: could not to chdir inside chroot to %s (does it exist?)\n", home); exit(2); } /* printf("Root now %s\n", home); */ /* revert to original user, or abort before we exec! */ if (0 != setuid(uid)) { printf("FAILED: could not reset uid\n"); exit(3); } /* read their real home from the password file in the secure area */ home = NULL; pw = getpwuid(uid); if (NULL == pw) { printf("WARNING: password data not available in secure section\n"); } else { home = pw->pw_dir; } if (NULL == home) { printf("WARNING: could not locate home directory\n"); } else { if (chdir(home)) { printf("WARNING: could not change to home directory\n"); } } /* fix the environment */ setenv("HOME", home, 1); setenv("PATH", "/bin:/usr/bin:/usr/local/bin", 1); setenv("LD_LIBRARY_PATH", "/usr/lib:/usr/local/lib", 1); setenv("SHELL", "/bin/sh", 1); /* build argument array to exec cmds int j; char *nargv[argc+2]; nargv[0]="-sh"; nargv[1]="-c"; for (j=0; j