]>
Commit | Line | Data |
---|---|---|
3d9156a7 A |
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> | |
3d9156a7 A |
24 | #include <sys/acl.h> |
25 | #include <errno.h> | |
26 | #include <fcntl.h> | |
27 | #include <unistd.h> | |
28 | #include <uuid/uuid.h> | |
29 | ||
30 | #if 1 /* for turdfile code only */ | |
31 | #include <string.h> | |
32 | #include <sys/stat.h> | |
33 | #include <stdio.h> | |
34 | #include <stdlib.h> | |
35 | #endif | |
36 | ||
34e8f829 A |
37 | static int chmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl); |
38 | static int fchmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl); | |
3d9156a7 A |
39 | |
40 | static int chmodx1(void *obj, | |
41 | int (* chmod_syscall)(void *obj, uid_t fsowner, gid_t fsgrp, int mode, | |
34e8f829 | 42 | kauth_filesec_t fsacl), |
3d9156a7 A |
43 | filesec_t fsec); |
44 | ||
45 | /* | |
46 | * Chmod interfaces. | |
47 | */ | |
48 | int | |
49 | chmodx_np(const char *path, filesec_t fsec) | |
50 | { | |
51 | return(chmodx1((void *)&path, chmodx_syscall, fsec)); | |
52 | } | |
53 | ||
54 | int | |
55 | fchmodx_np(int fd, filesec_t fsec) | |
56 | { | |
57 | return(chmodx1((void *)&fd, fchmodx_syscall, fsec)); | |
58 | } | |
59 | ||
60 | /* | |
61 | * Chmod syscalls. | |
62 | */ | |
34e8f829 A |
63 | extern int __chmod_extended(char *, uid_t, gid_t, int, kauth_filesec_t); |
64 | extern int __fchmod_extended(int, uid_t, gid_t, int, kauth_filesec_t); | |
224c7076 | 65 | |
3d9156a7 | 66 | static int |
34e8f829 | 67 | chmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl) |
3d9156a7 A |
68 | { |
69 | char *path = *(char **)obj; | |
70 | ||
224c7076 | 71 | return(__chmod_extended(path, fsowner, fsgrp, mode, fsacl)); |
3d9156a7 A |
72 | } |
73 | ||
74 | static int | |
34e8f829 | 75 | fchmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl) |
3d9156a7 A |
76 | { |
77 | int fd = *(int *)obj; | |
224c7076 | 78 | return(__fchmod_extended(fd, fsowner, fsgrp, mode, fsacl)); |
3d9156a7 A |
79 | } |
80 | ||
81 | /* | |
82 | * Chmod internals. | |
83 | */ | |
84 | ||
85 | static int | |
86 | chmodx1(void *obj, | |
34e8f829 | 87 | int (chmod_syscall)(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl), |
3d9156a7 A |
88 | filesec_t fsec) |
89 | { | |
90 | uid_t fsowner = KAUTH_UID_NONE; | |
91 | gid_t fsgrp = KAUTH_GID_NONE; | |
92 | mode_t fsec_mode; | |
93 | int fsmode = -1; | |
94 | size_t size = 0; | |
95 | int fsacl_used = 0; | |
96 | int delete_acl = 0; | |
34e8f829 | 97 | kauth_filesec_t fsacl = KAUTH_FILESEC_NONE; |
3d9156a7 A |
98 | struct kauth_filesec static_filesec; |
99 | ||
100 | if (fsec == NULL) { | |
101 | errno = EINVAL; | |
102 | return(-1); | |
103 | } | |
104 | ||
105 | /* regular properties */ | |
106 | if ((filesec_get_property(fsec, FILESEC_OWNER, &fsowner) != 0) && (errno != ENOENT)) | |
107 | return(-1); | |
108 | if ((filesec_get_property(fsec, FILESEC_GROUP, &fsgrp) != 0) && (errno != ENOENT)) | |
109 | return(-1); | |
110 | if ((filesec_get_property(fsec, FILESEC_MODE, &fsec_mode)) != 0) { | |
111 | if (errno != ENOENT) | |
112 | return(-1); | |
113 | } else { | |
114 | /* cast up */ | |
115 | fsmode = fsec_mode; | |
116 | } | |
117 | ||
118 | /* | |
119 | * We can set any or all of the ACL and UUIDs, but the two are transported in one | |
120 | * structure. If we have an ACL, we'll use its allocated structure, otherwise we | |
121 | * need our own. | |
122 | */ | |
123 | if (((filesec_get_property(fsec, FILESEC_ACL_RAW, &fsacl) != 0) || | |
124 | (filesec_get_property(fsec, FILESEC_ACL_ALLOCSIZE, &size) != 0)) && | |
125 | (errno != ENOENT)) | |
126 | return(-1); | |
127 | /* caller wants to delete ACL, must remember this */ | |
128 | if (fsacl == _FILESEC_REMOVE_ACL) { | |
129 | delete_acl = 1; | |
130 | fsacl = 0; | |
131 | } | |
132 | ||
133 | /* no ACL, use local filesec */ | |
34e8f829 | 134 | if (fsacl == KAUTH_FILESEC_NONE) { |
3d9156a7 A |
135 | bzero(&static_filesec, sizeof(static_filesec)); |
136 | fsacl = &static_filesec; | |
137 | fsacl->fsec_magic = KAUTH_FILESEC_MAGIC; | |
138 | fsacl->fsec_entrycount = KAUTH_FILESEC_NOACL; | |
139 | } else { | |
140 | fsacl_used = 1; | |
141 | } | |
142 | ||
143 | /* grab the owner and group UUID if present */ | |
144 | if (filesec_get_property(fsec, FILESEC_UUID, &fsacl->fsec_owner) != 0) { | |
145 | if (errno != ENOENT) | |
146 | return(-1); | |
147 | bzero(&fsacl->fsec_owner, sizeof(fsacl->fsec_owner)); | |
148 | } else { | |
149 | fsacl_used = 1; | |
150 | } | |
151 | if (filesec_get_property(fsec, FILESEC_GRPUUID, &fsacl->fsec_group) != 0) { | |
152 | if (errno != ENOENT) | |
153 | return(-1); | |
154 | bzero(&fsacl->fsec_group, sizeof(fsacl->fsec_group)); | |
155 | } else { | |
156 | fsacl_used = 1; | |
157 | } | |
158 | ||
159 | /* after all this, if we didn't find anything that needs it, don't pass it in */ | |
160 | if (!fsacl_used) { | |
161 | /* | |
162 | * If the caller was trying to remove the ACL, and there are no UUIDs, | |
163 | * we can tell the kernel to completely nuke the whole datastructure. | |
164 | */ | |
165 | if (delete_acl) { | |
166 | fsacl = _FILESEC_REMOVE_ACL; | |
167 | } else { | |
34e8f829 | 168 | fsacl = KAUTH_FILESEC_NONE; |
3d9156a7 A |
169 | } |
170 | } | |
171 | ||
172 | return(chmod_syscall(obj, fsowner, fsgrp, fsmode, fsacl)); | |
173 | } |