4 * Copyright (C) International Business Machines Corp., 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for mapping CIFS/NTFS ACLs
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.
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.
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
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
32 #ifdef CONFIG_CIFS_EXPERIMENTAL
34 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
35 {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
36 {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
37 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
38 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
39 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
40 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
41 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} }
45 /* security id for everyone */
46 static const struct cifs_sid sid_everyone =
47 {1, 1, {0, 0, 0, 0, 0, 0}, {} };
49 static const struct cifs_sid sid_user =
50 {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
53 int match_sid(struct cifs_sid *ctsid)
56 int num_subauth, num_sat, num_saw;
57 struct cifs_sid *cwsid;
62 for (i = 0; i < NUM_WK_SIDS; ++i) {
63 cwsid = &(wksidarr[i].cifssid);
65 /* compare the revision */
66 if (ctsid->revision != cwsid->revision)
69 /* compare all of the six auth values */
70 for (j = 0; j < 6; ++j) {
71 if (ctsid->authority[j] != cwsid->authority[j])
75 continue; /* all of the auth values did not match */
77 /* compare all of the subauth values if any */
78 num_sat = ctsid->num_subauth;
79 num_saw = cwsid->num_subauth;
80 num_subauth = num_sat < num_saw ? num_sat : num_saw;
82 for (j = 0; j < num_subauth; ++j) {
83 if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
87 continue; /* all sub_auth values do not match */
90 cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
91 return (0); /* sids compare/match */
94 cFYI(1, ("No matching sid"));
98 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
99 the same returns 1, if they do not match returns 0 */
100 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
103 int num_subauth, num_sat, num_saw;
105 if ((!ctsid) || (!cwsid))
108 /* compare the revision */
109 if (ctsid->revision != cwsid->revision)
112 /* compare all of the six auth values */
113 for (i = 0; i < 6; ++i) {
114 if (ctsid->authority[i] != cwsid->authority[i])
118 /* compare all of the subauth values if any */
119 num_sat = ctsid->num_subauth;
120 num_saw = cwsid->num_subauth;
121 num_subauth = num_sat < num_saw ? num_sat : num_saw;
123 for (i = 0; i < num_subauth; ++i) {
124 if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
129 return (1); /* sids compare/match */
133 change posix mode to reflect permissions
134 pmode is the existing mode (we only want to overwrite part of this
135 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
137 static void access_flags_to_mode(__u32 access_flags, umode_t * pmode,
141 #ifdef CONFIG_CIFS_DEBUG2
142 cFYI(1, ("access flags 0x%x mode now 0x%x", access_flags, *pmode);
148 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
150 void acl_to_uid_mode(struct inode *inode, const char *path)
152 struct cifsFileInfo *open_file;
153 int unlock_file = FALSE;
157 struct super_block *sb;
158 struct cifs_sb_info *cifs_sb;
160 cFYI(1, ("get mode from ACL for %s", path));
166 open_file = find_readable_file(CIFS_I(inode));
169 fid = open_file->netfid;
178 cifs_sb = CIFS_SB(sb);
179 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
180 GENERIC_READ, 0, &fid, &oplock, NULL,
181 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
182 CIFS_MOUNT_MAP_SPECIAL_CHR);
184 cERROR(1, ("Unable to open file to get ACL"));
190 /* rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, pntsd, acllen,
193 if (unlock_file == TRUE)
194 atomic_dec(&open_file->wrtPending);
196 CIFSSMBClose(xid, cifs_sb->tcon, fid);
199 rc = parse_sec_desc(pntsd, acllen, inode);
207 static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
211 /* validate that we do not go past end of acl */
213 if (le16_to_cpu(pace->size) < 16) {
214 cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
218 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
219 cERROR(1, ("ACL too small to parse ACE"));
223 num_subauth = pace->sid.num_subauth;
225 #ifdef CONFIG_CIFS_DEBUG2
227 cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
228 pace->sid.revision, pace->sid.num_subauth, pace->type,
229 pace->flags, pace->size));
230 for (i = 0; i < num_subauth; ++i) {
231 cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
232 le32_to_cpu(pace->sid.sub_auth[i])));
235 /* BB add length check to make sure that we do not have huge
236 num auths and therefore go off the end */
244 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
245 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid
252 struct cifs_ace **ppace;
254 /* BB need to add parm so we can store the SID BB */
256 /* validate that we do not go past end of acl */
257 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
258 cERROR(1, ("ACL too small to parse DACL"));
262 #ifdef CONFIG_CIFS_DEBUG2
263 cFYI(1, ("DACL revision %d size %d num aces %d",
264 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
265 le32_to_cpu(pdacl->num_aces)));
268 acl_base = (char *)pdacl;
269 acl_size = sizeof(struct cifs_acl);
271 num_aces = le32_to_cpu(pdacl->num_aces);
273 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
276 /* cifscred->cecount = pdacl->num_aces;
277 cifscred->aces = kmalloc(num_aces *
278 sizeof(struct cifs_ace *), GFP_KERNEL);*/
280 for (i = 0; i < num_aces; ++i) {
281 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
283 parse_ace(ppace[i], end_of_acl);
285 /* memcpy((void *)(&(cifscred->aces[i])),
287 sizeof(struct cifs_ace)); */
289 acl_base = (char *)ppace[i];
290 acl_size = le16_to_cpu(ppace[i]->size);
300 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
303 /* BB need to add parm so we can store the SID BB */
305 /* validate that we do not go past end of acl */
306 if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
307 cERROR(1, ("ACL too small to parse SID"));
311 if (psid->num_subauth) {
312 #ifdef CONFIG_CIFS_DEBUG2
314 cFYI(1, ("SID revision %d num_auth %d",
315 psid->revision, psid->num_subauth));
317 for (i = 0; i < psid->num_subauth; i++) {
318 cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
319 le32_to_cpu(psid->sub_auth[i])));
322 /* BB add length check to make sure that we do not have huge
323 num auths and therefore go off the end */
325 le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
333 /* Convert CIFS ACL to POSIX form */
334 static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
338 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
339 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
340 char *end_of_acl = ((char *)pntsd) + acl_len;
342 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
343 le32_to_cpu(pntsd->osidoffset));
344 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
345 le32_to_cpu(pntsd->gsidoffset));
346 dacl_ptr = (struct cifs_acl *)((char *)pntsd +
347 le32_to_cpu(pntsd->dacloffset));
348 #ifdef CONFIG_CIFS_DEBUG2
349 cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
350 "sacloffset 0x%x dacloffset 0x%x",
351 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
352 le32_to_cpu(pntsd->gsidoffset),
353 le32_to_cpu(pntsd->sacloffset),
354 le32_to_cpu(pntsd->dacloffset)));
356 rc = parse_sid(owner_sid_ptr, end_of_acl);
360 rc = parse_sid(group_sid_ptr, end_of_acl);
364 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, inode);
366 /* cifscred->uid = owner_sid_ptr->rid;
367 cifscred->gid = group_sid_ptr->rid;
368 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
369 sizeof(struct cifs_sid));
370 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
371 sizeof(struct cifs_sid)); */
376 #endif /* CONFIG_CIFS_EXPERIMENTAL */