Commit | Line | Data |
---|---|---|
bcb02034 SF |
1 | /* |
2 | * fs/cifs/cifsacl.c | |
3 | * | |
4 | * Copyright (C) International Business Machines Corp., 2007 | |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | |
6 | * | |
7 | * Contains the routines for mapping CIFS/NTFS ACLs | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU Lesser General Public License as published | |
11 | * by the Free Software Foundation; either version 2.1 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | |
17 | * the GNU Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public License | |
20 | * along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | ||
65874007 SF |
24 | #include <linux/fs.h> |
25 | #include "cifspdu.h" | |
26 | #include "cifsglob.h" | |
d0d66c44 | 27 | #include "cifsacl.h" |
65874007 SF |
28 | #include "cifsproto.h" |
29 | #include "cifs_debug.h" | |
65874007 | 30 | |
bcb02034 SF |
31 | /* security id for everyone */ |
32 | static const struct cifs_sid sid_everyone = | |
d0d66c44 | 33 | {1, 1, {0, 0, 0, 0, 0, 0}, {}}; |
bcb02034 SF |
34 | /* group users */ |
35 | static const struct cifs_sid sid_user = | |
d0d66c44 SP |
36 | {1, 2 , {0, 0, 0, 0, 0, 5}, {}}; |
37 | ||
38 | static void parse_ace(struct cifs_ace * pace, char * end_of_acl) | |
39 | { | |
40 | int i; | |
41 | int num_subauth; | |
42 | __u32 *psub_auth; | |
43 | ||
44 | /* validate that we do not go past end of acl */ | |
45 | if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { | |
46 | cERROR(1, ("ACL too small to parse ACE")); | |
47 | return; | |
48 | } | |
49 | ||
50 | num_subauth = cpu_to_le32(pace->num_subauth); | |
51 | if (num_subauth) { | |
52 | psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace)); | |
53 | #ifdef CONFIG_CIFS_DEBUG2 | |
54 | cFYI(1, ("ACE revision %d num_subauth %d", | |
55 | pace->revision, pace->num_subauth)); | |
56 | for (i = 0; i < num_subauth; ++i) { | |
57 | cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, | |
58 | le32_to_cpu(psub_auth[i]))); | |
59 | } | |
60 | ||
61 | /* BB add length check to make sure that we do not have huge | |
62 | num auths and therefore go off the end */ | |
63 | ||
64 | cFYI(1, ("RID %d", le32_to_cpu(psub_auth[num_subauth-1]))); | |
65 | #endif | |
66 | } | |
67 | ||
68 | return; | |
69 | } | |
70 | ||
71 | static void parse_ntace(struct cifs_ntace * pntace, char * end_of_acl) | |
72 | { | |
73 | /* validate that we do not go past end of acl */ | |
74 | if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) { | |
75 | cERROR(1, ("ACL too small to parse NT ACE")); | |
76 | return; | |
77 | } | |
78 | ||
79 | #ifdef CONFIG_CIFS_DEBUG2 | |
80 | cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x", | |
81 | pntace->type, pntace->flags, pntace->size, | |
82 | pntace->access_req)); | |
83 | #endif | |
84 | return; | |
85 | } | |
86 | ||
87 | ||
88 | ||
89 | static void parse_dacl(struct cifs_acl * pdacl, char * end_of_acl) | |
90 | { | |
91 | int i; | |
92 | int num_aces = 0; | |
93 | int acl_size; | |
94 | char *acl_base; | |
95 | struct cifs_ntace **ppntace; | |
96 | struct cifs_ace **ppace; | |
97 | ||
98 | /* BB need to add parm so we can store the SID BB */ | |
99 | ||
100 | /* validate that we do not go past end of acl */ | |
101 | if (end_of_acl < (char *)pdacl + pdacl->size) { | |
102 | cERROR(1, ("ACL too small to parse DACL")); | |
103 | return; | |
104 | } | |
105 | ||
106 | #ifdef CONFIG_CIFS_DEBUG2 | |
107 | cFYI(1, ("DACL revision %d size %d num aces %d", | |
108 | pdacl->revision, pdacl->size, pdacl->num_aces)); | |
109 | #endif | |
110 | ||
111 | acl_base = (char *)pdacl; | |
112 | acl_size = sizeof(struct cifs_acl); | |
113 | ||
114 | num_aces = cpu_to_le32(pdacl->num_aces); | |
115 | if (num_aces > 0) { | |
116 | ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), | |
117 | GFP_KERNEL); | |
118 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | |
119 | GFP_KERNEL); | |
120 | ||
121 | /* cifscred->cecount = pdacl->num_aces; | |
122 | cifscred->ntaces = kmalloc(num_aces * | |
123 | sizeof(struct cifs_ntace *), GFP_KERNEL); | |
124 | cifscred->aces = kmalloc(num_aces * | |
125 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | |
126 | ||
127 | ||
128 | for (i = 0; i < num_aces; ++i) { | |
129 | ppntace[i] = (struct cifs_ntace *) | |
130 | (acl_base + acl_size); | |
131 | ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] + | |
132 | sizeof(struct cifs_ntace)); | |
133 | ||
134 | parse_ntace(ppntace[i], end_of_acl); | |
135 | parse_ace(ppace[i], end_of_acl); | |
136 | ||
137 | /* memcpy((void *)(&(cifscred->ntaces[i])), | |
138 | (void *)ppntace[i], | |
139 | sizeof(struct cifs_ntace)); | |
140 | memcpy((void *)(&(cifscred->aces[i])), | |
141 | (void *)ppace[i], | |
142 | sizeof(struct cifs_ace)); */ | |
143 | ||
144 | acl_base = (char *)ppntace[i]; | |
145 | acl_size = cpu_to_le32(ppntace[i]->size); | |
146 | } | |
147 | ||
148 | kfree(ppace); | |
149 | kfree(ppntace); | |
150 | } | |
151 | ||
152 | return; | |
153 | } | |
154 | ||
bcb02034 SF |
155 | |
156 | static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |
157 | { | |
d0d66c44 SP |
158 | int i; |
159 | int num_subauth; | |
160 | __u32 *psub_auth; | |
161 | ||
bcb02034 SF |
162 | /* BB need to add parm so we can store the SID BB */ |
163 | ||
164 | /* validate that we do not go past end of acl */ | |
165 | if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { | |
d0d66c44 | 166 | cERROR(1, ("ACL too small to parse SID")); |
bcb02034 SF |
167 | return -EINVAL; |
168 | } | |
d0d66c44 SP |
169 | |
170 | num_subauth = cpu_to_le32(psid->num_subauth); | |
171 | if (num_subauth) { | |
172 | psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid)); | |
bcb02034 | 173 | #ifdef CONFIG_CIFS_DEBUG2 |
d0d66c44 SP |
174 | cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", |
175 | psid->revision, psid->num_subauth, psid->sub_auth[0])); | |
bcb02034 | 176 | |
d0d66c44 SP |
177 | for (i = 0; i < num_subauth; ++i) { |
178 | cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, | |
179 | le32_to_cpu(psub_auth[i]))); | |
180 | } | |
181 | ||
182 | /* BB add length check to make sure that we do not have huge | |
183 | num auths and therefore go off the end */ | |
184 | cFYI(1, ("RID 0x%x", | |
185 | le32_to_cpu(psid->sub_auth[psid->num_subauth]))); | |
bcb02034 | 186 | #endif |
d0d66c44 SP |
187 | } |
188 | ||
bcb02034 SF |
189 | return 0; |
190 | } | |
191 | ||
d0d66c44 | 192 | |
bcb02034 SF |
193 | /* Convert CIFS ACL to POSIX form */ |
194 | int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) | |
195 | { | |
d0d66c44 | 196 | int rc; |
bcb02034 SF |
197 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
198 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | |
bcb02034 SF |
199 | char *end_of_acl = ((char *)pntsd) + acl_len; |
200 | ||
201 | owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + | |
202 | cpu_to_le32(pntsd->osidoffset)); | |
203 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + | |
204 | cpu_to_le32(pntsd->gsidoffset)); | |
205 | dacl_ptr = (struct cifs_acl *)((char *)pntsd + | |
206 | cpu_to_le32(pntsd->dacloffset)); | |
207 | #ifdef CONFIG_CIFS_DEBUG2 | |
208 | cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " | |
209 | "sacloffset 0x%x dacloffset 0x%x", | |
210 | pntsd->revision, pntsd->type, | |
211 | pntsd->osidoffset, pntsd->gsidoffset, pntsd->sacloffset, | |
212 | pntsd->dacloffset)); | |
213 | #endif | |
214 | rc = parse_sid(owner_sid_ptr, end_of_acl); | |
215 | if (rc) | |
216 | return rc; | |
217 | ||
218 | rc = parse_sid(group_sid_ptr, end_of_acl); | |
219 | if (rc) | |
220 | return rc; | |
221 | ||
d0d66c44 SP |
222 | parse_dacl(dacl_ptr, end_of_acl); |
223 | ||
bcb02034 SF |
224 | /* cifscred->uid = owner_sid_ptr->rid; |
225 | cifscred->gid = group_sid_ptr->rid; | |
226 | memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, | |
227 | sizeof (struct cifs_sid)); | |
228 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | |
229 | sizeof (struct cifs_sid)); */ | |
230 | ||
bcb02034 SF |
231 | return (0); |
232 | } |