186d7f5d3SJohn Marino #include <sys/types.h>
286d7f5d3SJohn Marino #include <sys/jail.h>
386d7f5d3SJohn Marino #include <sys/wait.h>
486d7f5d3SJohn Marino #include <unistd.h>
586d7f5d3SJohn Marino #include <stdio.h>
686d7f5d3SJohn Marino #include <stdlib.h>
786d7f5d3SJohn Marino
886d7f5d3SJohn Marino void setup();
986d7f5d3SJohn Marino void teardown();
1086d7f5d3SJohn Marino
1186d7f5d3SJohn Marino uid_t unpriv_uid = 5000;
1286d7f5d3SJohn Marino gid_t unpriv_gid = 5000;
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino void
test(int (* fn)(),int expected,char * msg,char * msg2)1586d7f5d3SJohn Marino test(int (*fn)(), int expected, char *msg, char *msg2)
1686d7f5d3SJohn Marino {
1786d7f5d3SJohn Marino int retval;
1886d7f5d3SJohn Marino
1986d7f5d3SJohn Marino setup();
2086d7f5d3SJohn Marino retval = fn();
2186d7f5d3SJohn Marino teardown();
2286d7f5d3SJohn Marino
2386d7f5d3SJohn Marino printf("%s (%s): ", msg, msg2);
2486d7f5d3SJohn Marino
2586d7f5d3SJohn Marino if (retval == expected) {
2686d7f5d3SJohn Marino printf("OK\n");
2786d7f5d3SJohn Marino } else {
2886d7f5d3SJohn Marino printf("FAILED (was: %d, expected: %d)\n", retval, expected);
2986d7f5d3SJohn Marino }
3086d7f5d3SJohn Marino fflush(stdout);
3186d7f5d3SJohn Marino }
3286d7f5d3SJohn Marino
3386d7f5d3SJohn Marino void
test_as_root(int (* fn)(),int expected,char * msg)3486d7f5d3SJohn Marino test_as_root(int (*fn)(), int expected, char *msg)
3586d7f5d3SJohn Marino {
3686d7f5d3SJohn Marino if (getuid() != 0) {
3786d7f5d3SJohn Marino fprintf(stderr, "must be run as root\n");
3886d7f5d3SJohn Marino exit(-1);
3986d7f5d3SJohn Marino }
4086d7f5d3SJohn Marino
4186d7f5d3SJohn Marino test(fn, expected, msg, "as root");
4286d7f5d3SJohn Marino }
4386d7f5d3SJohn Marino
4486d7f5d3SJohn Marino void
test_as_jailed_root(int (* fn)(),int expected,char * msg)4586d7f5d3SJohn Marino test_as_jailed_root(int (*fn)(), int expected, char *msg)
4686d7f5d3SJohn Marino {
4786d7f5d3SJohn Marino if (getuid() != 0) {
4886d7f5d3SJohn Marino fprintf(stderr, "must be run as root\n");
4986d7f5d3SJohn Marino exit(-1);
5086d7f5d3SJohn Marino }
5186d7f5d3SJohn Marino
5286d7f5d3SJohn Marino int child = fork();
5386d7f5d3SJohn Marino
5486d7f5d3SJohn Marino if (child == -1) {
5586d7f5d3SJohn Marino fprintf(stderr, "fork failed\n");
5686d7f5d3SJohn Marino exit(-2);
5786d7f5d3SJohn Marino }
5886d7f5d3SJohn Marino
5986d7f5d3SJohn Marino if (child) {
6086d7f5d3SJohn Marino struct jail j;
6186d7f5d3SJohn Marino j.version = 1;
6286d7f5d3SJohn Marino j.path = "/";
6386d7f5d3SJohn Marino j.hostname = "jail";
6486d7f5d3SJohn Marino j.n_ips = 0;
6586d7f5d3SJohn Marino
6686d7f5d3SJohn Marino int jid = jail(&j);
6786d7f5d3SJohn Marino if (jid < 0) {
6886d7f5d3SJohn Marino fprintf(stderr, "jail failed\n");
6986d7f5d3SJohn Marino exit(-1); // TODO
7086d7f5d3SJohn Marino }
7186d7f5d3SJohn Marino test(fn, expected, msg, "as jailed root");
7286d7f5d3SJohn Marino exit(0);
7386d7f5d3SJohn Marino }
7486d7f5d3SJohn Marino else {
7586d7f5d3SJohn Marino waitpid(child, NULL, 0);
7686d7f5d3SJohn Marino }
7786d7f5d3SJohn Marino }
7886d7f5d3SJohn Marino
7986d7f5d3SJohn Marino void
test_as_unpriv(int (* fn)(),int expected,char * msg)8086d7f5d3SJohn Marino test_as_unpriv(int (*fn)(), int expected, char *msg)
8186d7f5d3SJohn Marino {
8286d7f5d3SJohn Marino if (getuid() != 0) {
8386d7f5d3SJohn Marino fprintf(stderr, "must be run as root\n");
8486d7f5d3SJohn Marino exit(-1);
8586d7f5d3SJohn Marino }
8686d7f5d3SJohn Marino
8786d7f5d3SJohn Marino int child = fork();
8886d7f5d3SJohn Marino
8986d7f5d3SJohn Marino if (child == -1) {
9086d7f5d3SJohn Marino fprintf(stderr, "fork failed\n");
9186d7f5d3SJohn Marino exit(-2);
9286d7f5d3SJohn Marino }
9386d7f5d3SJohn Marino
9486d7f5d3SJohn Marino if (child) {
9586d7f5d3SJohn Marino setgid(unpriv_gid);
9686d7f5d3SJohn Marino setuid(unpriv_uid);
9786d7f5d3SJohn Marino
9886d7f5d3SJohn Marino if (getuid() != unpriv_uid || getgid() != unpriv_gid) {
9986d7f5d3SJohn Marino fprintf(stderr, "setuid/gid failed\n");
10086d7f5d3SJohn Marino exit(-1); // TODO
10186d7f5d3SJohn Marino }
10286d7f5d3SJohn Marino test(fn, expected, msg, "as unpriv");
10386d7f5d3SJohn Marino exit(0);
10486d7f5d3SJohn Marino }
10586d7f5d3SJohn Marino else {
10686d7f5d3SJohn Marino waitpid(child, NULL, 0);
10786d7f5d3SJohn Marino }
10886d7f5d3SJohn Marino }
10986d7f5d3SJohn Marino
11086d7f5d3SJohn Marino void
test_as_jailed_unpriv(int (* fn)(),int expected,char * msg)11186d7f5d3SJohn Marino test_as_jailed_unpriv(int (*fn)(), int expected, char *msg)
11286d7f5d3SJohn Marino {
11386d7f5d3SJohn Marino if (getuid() != 0) {
11486d7f5d3SJohn Marino fprintf(stderr, "must be run as root\n");
11586d7f5d3SJohn Marino exit(-1);
11686d7f5d3SJohn Marino }
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino int child = fork();
11986d7f5d3SJohn Marino
12086d7f5d3SJohn Marino if (child == -1) {
12186d7f5d3SJohn Marino fprintf(stderr, "fork failed\n");
12286d7f5d3SJohn Marino exit(-2);
12386d7f5d3SJohn Marino }
12486d7f5d3SJohn Marino
12586d7f5d3SJohn Marino if (child) {
12686d7f5d3SJohn Marino struct jail j;
12786d7f5d3SJohn Marino j.version = 1;
12886d7f5d3SJohn Marino j.path = "/";
12986d7f5d3SJohn Marino j.hostname = "jail";
13086d7f5d3SJohn Marino j.n_ips = 0;
13186d7f5d3SJohn Marino
13286d7f5d3SJohn Marino int jid = jail(&j);
13386d7f5d3SJohn Marino if (jid < 0) {
13486d7f5d3SJohn Marino fprintf(stderr, "jail failed\n");
13586d7f5d3SJohn Marino exit(-1); // TODO
13686d7f5d3SJohn Marino }
13786d7f5d3SJohn Marino
13886d7f5d3SJohn Marino setgid(unpriv_gid);
13986d7f5d3SJohn Marino setuid(unpriv_uid);
14086d7f5d3SJohn Marino
14186d7f5d3SJohn Marino if (getuid() != unpriv_uid || getgid() != unpriv_gid) {
14286d7f5d3SJohn Marino fprintf(stderr, "setuid/gid failed\n");
14386d7f5d3SJohn Marino exit(-1); // TODO
14486d7f5d3SJohn Marino }
14586d7f5d3SJohn Marino test(fn, expected, msg, "as jailed unpriv");
14686d7f5d3SJohn Marino exit(0);
14786d7f5d3SJohn Marino }
14886d7f5d3SJohn Marino else {
14986d7f5d3SJohn Marino waitpid(child, NULL, 0);
15086d7f5d3SJohn Marino }
15186d7f5d3SJohn Marino }
152