1c2aa98e2SPeter Wemm /* 2c2aa98e2SPeter Wemm ** This program tests your system to see if you have the lovely 3c2aa98e2SPeter Wemm ** security-defeating semantics that an open with O_CREAT|O_EXCL 4c2aa98e2SPeter Wemm ** set will successfully open a file named by a symbolic link that 5c2aa98e2SPeter Wemm ** points to a non-existent file. Sadly, Posix is mute on what 6c2aa98e2SPeter Wemm ** should happen in this situation. 7c2aa98e2SPeter Wemm ** 8c2aa98e2SPeter Wemm ** Results to date: 9c2aa98e2SPeter Wemm ** AIX 3.2 OK 10c2aa98e2SPeter Wemm ** BSD family OK 11c2aa98e2SPeter Wemm ** BSD/OS 2.1 OK 12c2aa98e2SPeter Wemm ** FreeBSD 2.1 OK 13c2aa98e2SPeter Wemm ** DEC OSF/1 3.0 OK 14c2aa98e2SPeter Wemm ** HP-UX 9.04 FAIL 15c2aa98e2SPeter Wemm ** HP-UX 9.05 FAIL 16c2aa98e2SPeter Wemm ** HP-UX 9.07 OK 17c2aa98e2SPeter Wemm ** HP-UX 10.01 OK 18c2aa98e2SPeter Wemm ** HP-UX 10.10 OK 19c2aa98e2SPeter Wemm ** HP-UX 10.20 OK 20c2aa98e2SPeter Wemm ** Irix 5.3 OK 21c2aa98e2SPeter Wemm ** Irix 6.2 OK 22c2aa98e2SPeter Wemm ** Irix 6.3 OK 23c2aa98e2SPeter Wemm ** Irix 6.4 OK 24c2aa98e2SPeter Wemm ** Linux OK 25c2aa98e2SPeter Wemm ** NeXT 2.1 OK 26c2aa98e2SPeter Wemm ** Solaris 2.x OK 27c2aa98e2SPeter Wemm ** SunOS 4.x OK 28c2aa98e2SPeter Wemm ** Ultrix 4.3 OK 29c2aa98e2SPeter Wemm */ 30c2aa98e2SPeter Wemm 31c2aa98e2SPeter Wemm #include <stdio.h> 32c2aa98e2SPeter Wemm #include <errno.h> 33c2aa98e2SPeter Wemm #include <sys/types.h> 34c2aa98e2SPeter Wemm #include <sys/stat.h> 35c2aa98e2SPeter Wemm #include <fcntl.h> 36c2aa98e2SPeter Wemm 37c2aa98e2SPeter Wemm char Attacker[128]; 38c2aa98e2SPeter Wemm char Attackee[128]; 39c2aa98e2SPeter Wemm 40c2aa98e2SPeter Wemm main(argc, argv) 41c2aa98e2SPeter Wemm int argc; 42c2aa98e2SPeter Wemm char **argv; 43c2aa98e2SPeter Wemm { 44c2aa98e2SPeter Wemm struct stat st; 45c2aa98e2SPeter Wemm 46c2aa98e2SPeter Wemm sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL)); 47c2aa98e2SPeter Wemm sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL)); 48c2aa98e2SPeter Wemm 49c2aa98e2SPeter Wemm if (symlink(Attackee, Attacker) < 0) 50c2aa98e2SPeter Wemm { 51c2aa98e2SPeter Wemm printf("Could not create %s->%s symlink: %d\n", 52c2aa98e2SPeter Wemm Attacker, Attackee, errno); 53c2aa98e2SPeter Wemm bail(1); 54c2aa98e2SPeter Wemm } 55c2aa98e2SPeter Wemm (void) unlink(Attackee); 56c2aa98e2SPeter Wemm if (stat(Attackee, &st) >= 0) 57c2aa98e2SPeter Wemm { 58c2aa98e2SPeter Wemm printf("%s already exists -- remove and try again.\n", 59c2aa98e2SPeter Wemm Attackee); 60c2aa98e2SPeter Wemm bail(1); 61c2aa98e2SPeter Wemm } 62c2aa98e2SPeter Wemm if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0) 63c2aa98e2SPeter Wemm { 64c2aa98e2SPeter Wemm int saveerr = errno; 65c2aa98e2SPeter Wemm 66c2aa98e2SPeter Wemm if (stat(Attackee, &st) >= 0) 67c2aa98e2SPeter Wemm { 68c2aa98e2SPeter Wemm printf("Weird. Open failed but %s was created anyhow (errno = %d)\n", 69c2aa98e2SPeter Wemm Attackee, saveerr); 70c2aa98e2SPeter Wemm bail(1); 71c2aa98e2SPeter Wemm } 72c2aa98e2SPeter Wemm printf("Good show! Exclusive open works properly with symbolic links (errno = %d).\n", 73c2aa98e2SPeter Wemm saveerr); 74c2aa98e2SPeter Wemm bail(0); 75c2aa98e2SPeter Wemm } 76c2aa98e2SPeter Wemm if (stat(Attackee, &st) < 0) 77c2aa98e2SPeter Wemm { 78c2aa98e2SPeter Wemm printf("Weird. Open succeeded but %s was not created\n", 79c2aa98e2SPeter Wemm Attackee); 80c2aa98e2SPeter Wemm bail(2); 81c2aa98e2SPeter Wemm } 82c2aa98e2SPeter Wemm printf("Bad news: you can do an exclusive open through a symbolic link\n"); 83c2aa98e2SPeter Wemm printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n"); 84c2aa98e2SPeter Wemm bail(1); 85c2aa98e2SPeter Wemm } 86c2aa98e2SPeter Wemm 87c2aa98e2SPeter Wemm bail(stat) 88c2aa98e2SPeter Wemm int stat; 89c2aa98e2SPeter Wemm { 90c2aa98e2SPeter Wemm (void) unlink(Attacker); 91c2aa98e2SPeter Wemm (void) unlink(Attackee); 92c2aa98e2SPeter Wemm exit(stat); 93c2aa98e2SPeter Wemm } 94