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