1/*
2 * Copyright (c) 1999 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11/*
12**  This program tests your system to see if you have the lovely
13**  security-defeating semantics that an open with O_CREAT|O_EXCL
14**  set will successfully open a file named by a symbolic link that
15**  points to a non-existent file.  Sadly, Posix is mute on what
16**  should happen in this situation.
17**
18**  Results to date:
19**	AIX 3.2		OK
20**	BSD family	OK
21**	  BSD/OS 2.1	OK
22**	  FreeBSD 2.1	OK
23**	DEC OSF/1 3.0	OK
24**	HP-UX 9.04	FAIL
25**	HP-UX 9.05	FAIL
26**	HP-UX 9.07	OK
27**	HP-UX 10.01	OK
28**	HP-UX 10.10	OK
29**	HP-UX 10.20	OK
30**	Irix 5.3	OK
31**	Irix 6.2	OK
32**	Irix 6.3	OK
33**	Irix 6.4	OK
34**	Linux		OK
35**	NeXT 2.1	OK
36**	Solaris 2.x	OK
37**	SunOS 4.x	OK
38**	Ultrix 4.3	OK
39*/
40
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdio.h>
46#include <unistd.h>
47
48#ifndef lint
49static char id[] = "@(#)$Id: t_exclopen.c,v 8.7 2013-11-22 20:52:01 ca Exp $";
50#endif /* ! lint */
51
52static char Attacker[128];
53static char Attackee[128];
54
55static void
56bail(status)
57	int status;
58{
59	(void) unlink(Attacker);
60	(void) unlink(Attackee);
61	exit(status);
62}
63
64int
65main(argc, argv)
66	int argc;
67	char **argv;
68{
69	struct stat st;
70
71	sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL));
72	sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL));
73
74	if (symlink(Attackee, Attacker) < 0)
75	{
76		printf("Could not create %s->%s symlink: %d\n",
77			Attacker, Attackee, errno);
78		bail(1);
79	}
80	(void) unlink(Attackee);
81	if (stat(Attackee, &st) >= 0)
82	{
83		printf("%s already exists -- remove and try again.\n",
84			Attackee);
85		bail(1);
86	}
87	if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0)
88	{
89		int save_errno = errno;
90
91		if (stat(Attackee, &st) >= 0)
92		{
93			printf("Weird.  Open failed but %s was created anyhow (errno = %d)\n",
94				Attackee, save_errno);
95			bail(1);
96		}
97		printf("Good show!  Exclusive open works properly with symbolic links (errno = %d).\n",
98			save_errno);
99		bail(0);
100	}
101	if (stat(Attackee, &st) < 0)
102	{
103		printf("Weird.  Open succeeded but %s was not created\n",
104			Attackee);
105		bail(2);
106	}
107	printf("Bad news: you can do an exclusive open through a symbolic link\n");
108	printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n");
109	bail(1);
110
111	/* NOTREACHED */
112	exit(0);
113}
114