1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <sys/types.h>
24#include <sys/acl.h>
25#include <errno.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <string.h>
29
30enum {OPENX, MKFIFOX, MKDIRX};
31
32extern int __open_extended(const char *, int, uid_t, gid_t, int, struct kauth_filesec *);
33extern int __mkfifo_extended(const char *, uid_t, gid_t, int, struct kauth_filesec *);
34extern int __mkdir_extended(const char *, uid_t, gid_t, int, struct kauth_filesec *);
35
36static int
37_mkfilex_np(int opcode, const char *path, int flags, filesec_t fsec)
38{
39	uid_t owner = KAUTH_UID_NONE;
40	gid_t group = KAUTH_GID_NONE;
41	mode_t mode = 0;
42	size_t size = 0;
43	int fsacl_used = 0;
44	struct kauth_filesec *fsacl = NULL;
45	struct kauth_filesec static_filesec;
46
47	/* handle extended security data */
48	if (fsec != NULL) {
49		/* fetch basic parameters */
50		if ((filesec_get_property(fsec, FILESEC_OWNER, &owner) != 0) && (errno != ENOENT))
51			return(-1);
52		if ((filesec_get_property(fsec, FILESEC_GROUP, &group) != 0) && (errno != ENOENT))
53			return(-1);
54		if ((filesec_get_property(fsec, FILESEC_MODE, &mode) != 0) && (errno != ENOENT))
55			return(-1);
56
57		/* try to fetch the ACL */
58		if (((filesec_get_property(fsec, FILESEC_ACL_RAW, &fsacl) != 0) ||
59			(filesec_get_property(fsec, FILESEC_ACL_ALLOCSIZE, &size) != 0)) &&
60		    (errno != ENOENT))
61			return(-1);
62
63		/* only valid for chmod */
64		if (fsacl == _FILESEC_REMOVE_ACL) {
65			errno = EINVAL;
66			return(-1);
67		}
68
69		/* no ACL, use local filesec */
70		if (fsacl == NULL) {
71			bzero(&static_filesec, sizeof(static_filesec));
72			fsacl = &static_filesec;
73			fsacl->fsec_magic = KAUTH_FILESEC_MAGIC;
74			fsacl->fsec_entrycount = KAUTH_FILESEC_NOACL;
75		} else {
76			fsacl_used = 1;
77		}
78
79		/* grab the owner and group UUID if present */
80		if (filesec_get_property(fsec, FILESEC_UUID, &fsacl->fsec_owner) != 0) {
81			if (errno != ENOENT)
82				return(-1);
83			bzero(&fsacl->fsec_owner, sizeof(fsacl->fsec_owner));
84		} else {
85			fsacl_used = 1;
86		}
87		if (filesec_get_property(fsec, FILESEC_GRPUUID, &fsacl->fsec_group) != 0) {
88			if (errno != ENOENT)
89				return(-1);
90			bzero(&fsacl->fsec_group, sizeof(fsacl->fsec_group));
91		} else {
92			fsacl_used = 1;
93		}
94
95		/* after all this, if we didn't find anything that needs it, don't pass it in */
96		if (!fsacl_used)
97			fsacl = NULL;
98	}
99
100	switch (opcode) {
101	case OPENX:
102		return(__open_extended(path, flags, owner, group, mode, fsacl));
103	case MKFIFOX:
104		return(__mkfifo_extended(path, owner, group, mode, fsacl));
105	case MKDIRX:
106		return(__mkdir_extended(path, owner, group, mode, fsacl));
107	}
108	/* should never get here */
109	errno = EINVAL;
110	return(-1);
111}
112
113int
114openx_np(const char *path, int flags, filesec_t fsec)
115{
116	/* optimise for the simple case */
117	if (!(flags & O_CREAT) || (fsec == NULL))
118		return(open(path, flags));
119	return(_mkfilex_np(OPENX, path, flags, fsec));
120}
121
122int
123mkfifox_np(const char *path, filesec_t fsec)
124{
125	return(_mkfilex_np(MKFIFOX, path, 0, fsec));
126}
127
128int
129mkdirx_np(const char *path, filesec_t fsec)
130{
131	return(_mkfilex_np(MKDIRX, path, 0, fsec));
132}
133