diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jstart.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/jstart.c b/src/jstart.c new file mode 100644 index 0000000..b244aa4 --- /dev/null +++ b/src/jstart.c @@ -0,0 +1,134 @@ + +/* A lot of code from jail.c in */ +/* TODO: Attribute properly */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/jail.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <paths.h> +#include <stdio.h> +#include <err.h> +#include <unistd.h> +#include <limits.h> + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#define START_SCRIPT "/etc/rc" +static char* START_ARGS[] = { _PATH_BSHELL, START_SCRIPT }; + +static void usage(); +static void check_command(const char* cmd); +static void run_command(const char* cmd, char* args[]); + +int main(int argc, char* argv[]) +{ + int ch; + struct jail j; + struct in_addr in; + + argc--; + argv++; + + if(argc < 3) + usage(); + + if(getuid() != 0) + errx(1, "must be run as root"); + + if(chdir(argv[0]) != 0) + err(1, "couldn't change to jail directory: %s", argv[0]); + + if(inet_aton(argv[2], &in) != 1) + errx(1, "invalid ip address: %s", argv[2]); + + memset(&j, 0, sizeof(j)); + j.version = 0; + j.path = argv[0]; + j.hostname = argv[1]; + j.ip_number = ntohl(in.s_addr); + + /* Here's where we actually go into the jail */ + if(jail(&j) != 0) + err(1, "couldn't create jail"); + + argc -= 3; + argv += 3; + + if(argc == 0) + { + check_command(START_SCRIPT); + run_command(START_ARGS[0], START_ARGS); + } + + else + { + check_command(argv[0]); + run_command(argv[0], argv); + } + + return 0; +} + +static void usage() +{ + fprintf(stderr, "usage: jstart path hostname ip-number [command ...]\n"); + exit(2); +} + +static void check_command(const char* cmd) +{ + struct stat sb; + + if(stat(cmd, &sb) == -1) + { + if(errno == EACCES || errno == ELOOP || errno == ENAMETOOLONG || + errno == ENOENT || errno == ENOTDIR) + { + err(1, "can't execute in jail: %s", cmd); + } + + err(1, "couldn't stat file: %s", cmd); + } + + if(!(sb.st_mode & S_IFREG)) + errx(1, "not a regular file: %s", cmd); + + if(sb.st_uid != 0) + errx(1, "not owned by root: %s", cmd); +} + +static void run_command(const char* cmd, char* args[]) +{ + char* env[5]; + char* t; + int j; + + memset(env, 0, sizeof(env)); + +#define MAKE_ENV_VAR(n) \ + t = getenv(n); \ + if(t != NULL) \ + { \ + env[j] = alloca(strlen(n) + 2 + strlen(t)); \ + sprintf(env[j], "%s=%s", (char*)(n), t); \ + j++; \ + } + + /* Prepare an environment for the cmd */ + env[0] = "PATH=" _PATH_STDPATH; + j = 1; + + MAKE_ENV_VAR("TERM"); + MAKE_ENV_VAR("COLUMNS"); + MAKE_ENV_VAR("LINES"); + + if(execve(cmd, args, env) != 0) + err("couldn't execute command: %s", cmd); +} + |