193 lines
3.9 KiB
C
193 lines
3.9 KiB
C
/* test 11 */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
#define ITERATIONS 10
|
|
int max_error = 1;
|
|
#include "common.h"
|
|
|
|
|
|
int errct, subtest;
|
|
char *envp[3] = {"spring", "summer", 0};
|
|
char *passwd_file = "/etc/passwd";
|
|
|
|
|
|
int main(int argc, char *argv[]);
|
|
void test11a(void);
|
|
void test11b(void);
|
|
void test11c(void);
|
|
void test11d(void);
|
|
|
|
int main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
int i, m = 0xFFFF;
|
|
|
|
if (argc == 2) m = atoi(argv[1]);
|
|
|
|
start(11);
|
|
|
|
system("cp ../t11a .");
|
|
system("cp ../t11b .");
|
|
|
|
if (geteuid() != 0) {
|
|
printf("must be setuid root; test aborted\n");
|
|
exit(1);
|
|
}
|
|
if (getuid() == 0) {
|
|
printf("must be setuid root logged in as someone else; test aborted\n");
|
|
exit(1);
|
|
}
|
|
|
|
for (i = 0; i < ITERATIONS; i++) {
|
|
if (m & 0001) test11a();
|
|
if (m & 0002) test11b();
|
|
if (m & 0004) test11c();
|
|
if (m & 0010) test11d();
|
|
}
|
|
quit();
|
|
return(-1);
|
|
}
|
|
|
|
void test11a()
|
|
{
|
|
/* Test exec */
|
|
int n, fd;
|
|
char aa[4];
|
|
|
|
subtest = 1;
|
|
|
|
if (fork()) {
|
|
wait(&n);
|
|
if (n != 25600) e(1);
|
|
unlink("t1");
|
|
unlink("t2");
|
|
} else {
|
|
if (chown("t11a", 10, 20) < 0) e(2);
|
|
chmod("t11a", 0666);
|
|
|
|
/* The following call should fail because the mode has no X
|
|
* bits on. If a bug lets it unexpectedly succeed, the child
|
|
* will print an error message since the arguments are wrong.
|
|
*/
|
|
execl("t11a", "t11a", (char *) 0); /* should fail -- no X bits */
|
|
|
|
/* Control should come here after the failed execl(). */
|
|
chmod("t11a", 06555);
|
|
if ((fd = creat("t1", 0600)) != 3) e(3);
|
|
if (close(fd) < 0) e(4);
|
|
if (open("t1", O_RDWR) != 3) e(5);
|
|
if (chown("t1", 10, 99) < 0) e(6);
|
|
if ((fd = creat("t2", 0060)) != 4) e(7);
|
|
if (close(fd) < 0) e(8);
|
|
if (open("t2", O_RDWR) != 4) e(9);
|
|
if (chown("t2", 99, 20) < 0) e(10);
|
|
if (setgid(6) < 0) e(11);
|
|
if (setuid(5) < 0) e(12);
|
|
if (getuid() != 5) e(13);
|
|
if (geteuid() != 5) e(14);
|
|
if (getgid() != 6) e(15);
|
|
if (getegid() != 6) e(16);
|
|
aa[0] = 3;
|
|
aa[1] = 5;
|
|
aa[2] = 7;
|
|
aa[3] = 9;
|
|
if (write(3, aa, 4) != 4) e(17);
|
|
lseek(3, 2L, 0);
|
|
execle("t11a", "t11a", "arg0", "arg1", "arg2", (char *) 0, envp);
|
|
e(18);
|
|
printf("Can't exec t11a\n");
|
|
exit(3);
|
|
}
|
|
}
|
|
|
|
void test11b()
|
|
{
|
|
int n;
|
|
char *argv[5];
|
|
|
|
subtest = 2;
|
|
if (fork()) {
|
|
wait(&n);
|
|
if (n != (75 << 8)) e(20);
|
|
} else {
|
|
/* Child tests execv. */
|
|
argv[0] = "t11b";
|
|
argv[1] = "abc";
|
|
argv[2] = "defghi";
|
|
argv[3] = "j";
|
|
argv[4] = 0;
|
|
execv("t11b", argv);
|
|
e(19);
|
|
}
|
|
}
|
|
|
|
void test11c()
|
|
{
|
|
/* Test getlogin(). This test MUST run setuid root. */
|
|
|
|
int n, etc_uid;
|
|
uid_t ruid, euid;
|
|
char *lnamep, *p;
|
|
#define MAXLINELEN 200
|
|
char array[MAXLINELEN], save[L_cuserid];
|
|
FILE *stream;
|
|
|
|
subtest = 3;
|
|
errno = -2000; /* None of these calls set errno. */
|
|
save[0] = '#';
|
|
save[1] = '0';
|
|
ruid = getuid();
|
|
euid = geteuid();
|
|
lnamep = getlogin();
|
|
strcpy(save, lnamep);
|
|
|
|
/* Because we are setuid, login != 'root' */
|
|
if (euid != 0) e(1);
|
|
if (ruid == 0) e(2);
|
|
if ( (n = strlen(save)) == 0) e(5);
|
|
|
|
/* Check login against passwd file. First lookup login in /etc/passwd. */
|
|
if (n == 0) return; /* if login not found, don't look it up */
|
|
if ( (stream = fopen(passwd_file, "r")) == NULL) e(8);
|
|
while (fgets(array, sizeof(array), stream) != NULL) {
|
|
if (strncmp(array, save, n) == 0) {
|
|
p = &array[0]; /* hunt for uid */
|
|
while (*p != ':') p++;
|
|
p++;
|
|
while (*p != ':') p++;
|
|
p++; /* p now points to uid */
|
|
etc_uid = atoi(p);
|
|
if (etc_uid != ruid) e(9);
|
|
break; /* 1 entry per login please */
|
|
}
|
|
}
|
|
fclose(stream);
|
|
}
|
|
|
|
void test11d()
|
|
{
|
|
int fd;
|
|
struct stat statbuf;
|
|
|
|
subtest = 4;
|
|
fd = creat("T11.1", 0750);
|
|
if (fd < 0) e(1);
|
|
if (chown("T11.1", 8, 1) != 0) e(2);
|
|
if (chmod("T11.1", 0666) != 0) e(3);
|
|
if (stat("T11.1", &statbuf) != 0) e(4);
|
|
if ((statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) != 0666) e(5);
|
|
if (close(fd) != 0) e(6);
|
|
if (unlink("T11.1") != 0) e(7);
|
|
}
|
|
|