这是
http://blog.csdn.net/Braveo/archive/2008/09/09/2902996.aspx
的改进版。支持命令行。写这个程序的目的是让一个普通用户在登陆后可以通过调用这个shell是入某个指定的chroot根,并使用某个指定的用户。我用了一段时间,觉得挺有实际意义。用法在usage()中列出了。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#define JAILROOT "/home/myroot"
#define JAILSHELL "/bin/bash"
#define JAILGROUP 500
#define JAILUSER 500
#define JAILHOME "/home/jail"
#define JAILPATH "/sbin:/usr/sbin:/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/bin:/usr/bin"
void usage(const char * prog)
{
fprintf(stderr, "Usage: %s [options]/n"
"/t-r <root>: chroot的目标目录./n"
"/t-s <shell>: shell程序,如/bin/bash./n"
"/t-g <groupid>: chroot后转换成的普通用户的用户组号,需要数字格式,如500/n"
"/t-u <userid>: chroot后转换成的普通用户的用户号,需要数字格式,如500/n"
"/t-H <home>: chroot后作为用户home目录的路径/n"
"/t-p <path>: chroot后用户的PATH值/n"
, prog);
}
#define OPTIONS "r:s:g:u:H:p:h:"
int main(int argc, char **argv)
{
int ch;
const char * jail_root = JAILROOT;
const char * jail_shell = JAILSHELL;
int jail_group = JAILGROUP;
int jail_user = JAILUSER;
const char * jail_home = JAILHOME;
const char * jail_path = JAILPATH;
const char * prog = argv[0];
while((ch = getopt(argc, argv, OPTIONS))!=-1)
{
switch(ch)
{
case 'r':
jail_root = optarg;
break;
case 's':
jail_shell = optarg;
break;
case 'g':
jail_group = atoi(optarg);
break;
case 'u':
jail_user = atoi(optarg);
break;
case 'H':
jail_home = optarg;
break;
case 'p':
jail_path = optarg;
break;
case 'h':
case '?':
default:
usage(prog);
exit(0);
}
}
argc -= optind;
argv += optind;
int i;
chdir(JAILROOT);
i=chroot(JAILROOT);
if(i!=0)
{
perror("chroot");
}
if(argc>1&&strcmp(argv[0],"root")==0)
{
system(JAILSHELL);
}
else
{
setenv("HOME", jail_home, 1);
setenv("SHELL", jail_shell, 1);
setenv("PATH", jail_path, 1);
setgid(jail_group);
setuid(jail_user);
chdir(jail_home);
//system(JAILSHELL);
execl(jail_shell, jail_shell, NULL);
perror("execl: ");
}
}