• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   fs/cifs/cifsacl.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2007,2008
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 
24 #include <linux/fs.h>
25 #include "cifspdu.h"
26 #include "cifsglob.h"
27 #include "cifsacl.h"
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
30 
31 
32 #ifdef CONFIG_CIFS_EXPERIMENTAL
33 
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}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
38 	{{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
39 	{{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"},
40 	{{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"},
41 	{{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} }
42 ;
43 
44 
45 /* security id for everyone */
46 static const struct cifs_sid sid_everyone = {
47 	1, 1, {0, 0, 0, 0, 0, 1}, {0} };
48 /* group users */
49 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
50 
51 
match_sid(struct cifs_sid * ctsid)52 int match_sid(struct cifs_sid *ctsid)
53 {
54 	int i, j;
55 	int num_subauth, num_sat, num_saw;
56 	struct cifs_sid *cwsid;
57 
58 	if (!ctsid)
59 		return -1;
60 
61 	for (i = 0; i < NUM_WK_SIDS; ++i) {
62 		cwsid = &(wksidarr[i].cifssid);
63 
64 		/* compare the revision */
65 		if (ctsid->revision != cwsid->revision)
66 			continue;
67 
68 		/* compare all of the six auth values */
69 		for (j = 0; j < 6; ++j) {
70 			if (ctsid->authority[j] != cwsid->authority[j])
71 				break;
72 		}
73 		if (j < 6)
74 			continue; /* all of the auth values did not match */
75 
76 		/* compare all of the subauth values if any */
77 		num_sat = ctsid->num_subauth;
78 		num_saw = cwsid->num_subauth;
79 		num_subauth = num_sat < num_saw ? num_sat : num_saw;
80 		if (num_subauth) {
81 			for (j = 0; j < num_subauth; ++j) {
82 				if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
83 					break;
84 			}
85 			if (j < num_subauth)
86 				continue; /* all sub_auth values do not match */
87 		}
88 
89 		cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
90 		return 0; /* sids compare/match */
91 	}
92 
93 	cFYI(1, ("No matching sid"));
94 	return -1;
95 }
96 
97 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
98    the same returns 1, if they do not match returns 0 */
compare_sids(const struct cifs_sid * ctsid,const struct cifs_sid * cwsid)99 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
100 {
101 	int i;
102 	int num_subauth, num_sat, num_saw;
103 
104 	if ((!ctsid) || (!cwsid))
105 		return 0;
106 
107 	/* compare the revision */
108 	if (ctsid->revision != cwsid->revision)
109 		return 0;
110 
111 	/* compare all of the six auth values */
112 	for (i = 0; i < 6; ++i) {
113 		if (ctsid->authority[i] != cwsid->authority[i])
114 			return 0;
115 	}
116 
117 	/* compare all of the subauth values if any */
118 	num_sat = ctsid->num_subauth;
119 	num_saw = cwsid->num_subauth;
120 	num_subauth = num_sat < num_saw ? num_sat : num_saw;
121 	if (num_subauth) {
122 		for (i = 0; i < num_subauth; ++i) {
123 			if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
124 				return 0;
125 		}
126 	}
127 
128 	return 1; /* sids compare/match */
129 }
130 
131 
132 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
copy_sec_desc(const struct cifs_ntsd * pntsd,struct cifs_ntsd * pnntsd,__u32 sidsoffset)133 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
134 				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
135 {
136 	int i;
137 
138 	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
139 	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
140 
141 	/* copy security descriptor control portion */
142 	pnntsd->revision = pntsd->revision;
143 	pnntsd->type = pntsd->type;
144 	pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
145 	pnntsd->sacloffset = 0;
146 	pnntsd->osidoffset = cpu_to_le32(sidsoffset);
147 	pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
148 
149 	/* copy owner sid */
150 	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
151 				le32_to_cpu(pntsd->osidoffset));
152 	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
153 
154 	nowner_sid_ptr->revision = owner_sid_ptr->revision;
155 	nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
156 	for (i = 0; i < 6; i++)
157 		nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
158 	for (i = 0; i < 5; i++)
159 		nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
160 
161 	/* copy group sid */
162 	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
163 				le32_to_cpu(pntsd->gsidoffset));
164 	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
165 					sizeof(struct cifs_sid));
166 
167 	ngroup_sid_ptr->revision = group_sid_ptr->revision;
168 	ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
169 	for (i = 0; i < 6; i++)
170 		ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
171 	for (i = 0; i < 5; i++)
172 		ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
173 
174 	return;
175 }
176 
177 
178 /*
179    change posix mode to reflect permissions
180    pmode is the existing mode (we only want to overwrite part of this
181    bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
182 */
access_flags_to_mode(__le32 ace_flags,int type,umode_t * pmode,umode_t * pbits_to_set)183 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
184 				 umode_t *pbits_to_set)
185 {
186 	__u32 flags = le32_to_cpu(ace_flags);
187 	/* the order of ACEs is important.  The canonical order is to begin with
188 	   DENY entries followed by ALLOW, otherwise an allow entry could be
189 	   encountered first, making the subsequent deny entry like "dead code"
190 	   which would be superflous since Windows stops when a match is made
191 	   for the operation you are trying to perform for your user */
192 
193 	/* For deny ACEs we change the mask so that subsequent allow access
194 	   control entries do not turn on the bits we are denying */
195 	if (type == ACCESS_DENIED) {
196 		if (flags & GENERIC_ALL)
197 			*pbits_to_set &= ~S_IRWXUGO;
198 
199 		if ((flags & GENERIC_WRITE) ||
200 			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
201 			*pbits_to_set &= ~S_IWUGO;
202 		if ((flags & GENERIC_READ) ||
203 			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
204 			*pbits_to_set &= ~S_IRUGO;
205 		if ((flags & GENERIC_EXECUTE) ||
206 			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
207 			*pbits_to_set &= ~S_IXUGO;
208 		return;
209 	} else if (type != ACCESS_ALLOWED) {
210 		cERROR(1, ("unknown access control type %d", type));
211 		return;
212 	}
213 	/* else ACCESS_ALLOWED type */
214 
215 	if (flags & GENERIC_ALL) {
216 		*pmode |= (S_IRWXUGO & (*pbits_to_set));
217 		cFYI(DBG2, ("all perms"));
218 		return;
219 	}
220 	if ((flags & GENERIC_WRITE) ||
221 			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
222 		*pmode |= (S_IWUGO & (*pbits_to_set));
223 	if ((flags & GENERIC_READ) ||
224 			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
225 		*pmode |= (S_IRUGO & (*pbits_to_set));
226 	if ((flags & GENERIC_EXECUTE) ||
227 			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
228 		*pmode |= (S_IXUGO & (*pbits_to_set));
229 
230 	cFYI(DBG2, ("access flags 0x%x mode now 0x%x", flags, *pmode));
231 	return;
232 }
233 
234 /*
235    Generate access flags to reflect permissions mode is the existing mode.
236    This function is called for every ACE in the DACL whose SID matches
237    with either owner or group or everyone.
238 */
239 
mode_to_access_flags(umode_t mode,umode_t bits_to_use,__u32 * pace_flags)240 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
241 				__u32 *pace_flags)
242 {
243 	/* reset access mask */
244 	*pace_flags = 0x0;
245 
246 	/* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
247 	mode &= bits_to_use;
248 
249 	/* check for R/W/X UGO since we do not know whose flags
250 	   is this but we have cleared all the bits sans RWX for
251 	   either user or group or other as per bits_to_use */
252 	if (mode & S_IRUGO)
253 		*pace_flags |= SET_FILE_READ_RIGHTS;
254 	if (mode & S_IWUGO)
255 		*pace_flags |= SET_FILE_WRITE_RIGHTS;
256 	if (mode & S_IXUGO)
257 		*pace_flags |= SET_FILE_EXEC_RIGHTS;
258 
259 	cFYI(DBG2, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags));
260 	return;
261 }
262 
fill_ace_for_sid(struct cifs_ace * pntace,const struct cifs_sid * psid,__u64 nmode,umode_t bits)263 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
264 			const struct cifs_sid *psid, __u64 nmode, umode_t bits)
265 {
266 	int i;
267 	__u16 size = 0;
268 	__u32 access_req = 0;
269 
270 	pntace->type = ACCESS_ALLOWED;
271 	pntace->flags = 0x0;
272 	mode_to_access_flags(nmode, bits, &access_req);
273 	if (!access_req)
274 		access_req = SET_MINIMUM_RIGHTS;
275 	pntace->access_req = cpu_to_le32(access_req);
276 
277 	pntace->sid.revision = psid->revision;
278 	pntace->sid.num_subauth = psid->num_subauth;
279 	for (i = 0; i < 6; i++)
280 		pntace->sid.authority[i] = psid->authority[i];
281 	for (i = 0; i < psid->num_subauth; i++)
282 		pntace->sid.sub_auth[i] = psid->sub_auth[i];
283 
284 	size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
285 	pntace->size = cpu_to_le16(size);
286 
287 	return size;
288 }
289 
290 
291 #ifdef CONFIG_CIFS_DEBUG2
dump_ace(struct cifs_ace * pace,char * end_of_acl)292 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
293 {
294 	int num_subauth;
295 
296 	/* validate that we do not go past end of acl */
297 
298 	if (le16_to_cpu(pace->size) < 16) {
299 		cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
300 		return;
301 	}
302 
303 	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
304 		cERROR(1, ("ACL too small to parse ACE"));
305 		return;
306 	}
307 
308 	num_subauth = pace->sid.num_subauth;
309 	if (num_subauth) {
310 		int i;
311 		cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
312 			pace->sid.revision, pace->sid.num_subauth, pace->type,
313 			pace->flags, le16_to_cpu(pace->size)));
314 		for (i = 0; i < num_subauth; ++i) {
315 			cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
316 				le32_to_cpu(pace->sid.sub_auth[i])));
317 		}
318 
319 		/* BB add length check to make sure that we do not have huge
320 			num auths and therefore go off the end */
321 	}
322 
323 	return;
324 }
325 #endif
326 
327 
parse_dacl(struct cifs_acl * pdacl,char * end_of_acl,struct cifs_sid * pownersid,struct cifs_sid * pgrpsid,struct inode * inode)328 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
329 		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
330 		       struct inode *inode)
331 {
332 	int i;
333 	int num_aces = 0;
334 	int acl_size;
335 	char *acl_base;
336 	struct cifs_ace **ppace;
337 
338 	/* BB need to add parm so we can store the SID BB */
339 
340 	if (!pdacl) {
341 		/* no DACL in the security descriptor, set
342 		   all the permissions for user/group/other */
343 		inode->i_mode |= S_IRWXUGO;
344 		return;
345 	}
346 
347 	/* validate that we do not go past end of acl */
348 	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
349 		cERROR(1, ("ACL too small to parse DACL"));
350 		return;
351 	}
352 
353 	cFYI(DBG2, ("DACL revision %d size %d num aces %d",
354 		le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
355 		le32_to_cpu(pdacl->num_aces)));
356 
357 	/* reset rwx permissions for user/group/other.
358 	   Also, if num_aces is 0 i.e. DACL has no ACEs,
359 	   user/group/other have no permissions */
360 	inode->i_mode &= ~(S_IRWXUGO);
361 
362 	acl_base = (char *)pdacl;
363 	acl_size = sizeof(struct cifs_acl);
364 
365 	num_aces = le32_to_cpu(pdacl->num_aces);
366 	if (num_aces  > 0) {
367 		umode_t user_mask = S_IRWXU;
368 		umode_t group_mask = S_IRWXG;
369 		umode_t other_mask = S_IRWXO;
370 
371 		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
372 				GFP_KERNEL);
373 
374 		for (i = 0; i < num_aces; ++i) {
375 			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
376 #ifdef CONFIG_CIFS_DEBUG2
377 			dump_ace(ppace[i], end_of_acl);
378 #endif
379 			if (compare_sids(&(ppace[i]->sid), pownersid))
380 				access_flags_to_mode(ppace[i]->access_req,
381 						     ppace[i]->type,
382 						     &(inode->i_mode),
383 						     &user_mask);
384 			if (compare_sids(&(ppace[i]->sid), pgrpsid))
385 				access_flags_to_mode(ppace[i]->access_req,
386 						     ppace[i]->type,
387 						     &(inode->i_mode),
388 						     &group_mask);
389 			if (compare_sids(&(ppace[i]->sid), &sid_everyone))
390 				access_flags_to_mode(ppace[i]->access_req,
391 						     ppace[i]->type,
392 						     &(inode->i_mode),
393 						     &other_mask);
394 
395 /*			memcpy((void *)(&(cifscred->aces[i])),
396 				(void *)ppace[i],
397 				sizeof(struct cifs_ace)); */
398 
399 			acl_base = (char *)ppace[i];
400 			acl_size = le16_to_cpu(ppace[i]->size);
401 		}
402 
403 		kfree(ppace);
404 	}
405 
406 	return;
407 }
408 
409 
set_chmod_dacl(struct cifs_acl * pndacl,struct cifs_sid * pownersid,struct cifs_sid * pgrpsid,__u64 nmode)410 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
411 			struct cifs_sid *pgrpsid, __u64 nmode)
412 {
413 	u16 size = 0;
414 	struct cifs_acl *pnndacl;
415 
416 	pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
417 
418 	size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
419 					pownersid, nmode, S_IRWXU);
420 	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
421 					pgrpsid, nmode, S_IRWXG);
422 	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
423 					 &sid_everyone, nmode, S_IRWXO);
424 
425 	pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
426 	pndacl->num_aces = cpu_to_le32(3);
427 
428 	return 0;
429 }
430 
431 
parse_sid(struct cifs_sid * psid,char * end_of_acl)432 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
433 {
434 	/* BB need to add parm so we can store the SID BB */
435 
436 	/* validate that we do not go past end of ACL - sid must be at least 8
437 	   bytes long (assuming no sub-auths - e.g. the null SID */
438 	if (end_of_acl < (char *)psid + 8) {
439 		cERROR(1, ("ACL too small to parse SID %p", psid));
440 		return -EINVAL;
441 	}
442 
443 	if (psid->num_subauth) {
444 #ifdef CONFIG_CIFS_DEBUG2
445 		int i;
446 		cFYI(1, ("SID revision %d num_auth %d",
447 			psid->revision, psid->num_subauth));
448 
449 		for (i = 0; i < psid->num_subauth; i++) {
450 			cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
451 				le32_to_cpu(psid->sub_auth[i])));
452 		}
453 
454 		/* BB add length check to make sure that we do not have huge
455 			num auths and therefore go off the end */
456 		cFYI(1, ("RID 0x%x",
457 			le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
458 #endif
459 	}
460 
461 	return 0;
462 }
463 
464 
465 /* Convert CIFS ACL to POSIX form */
parse_sec_desc(struct cifs_ntsd * pntsd,int acl_len,struct inode * inode)466 static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
467 			  struct inode *inode)
468 {
469 	int rc;
470 	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
471 	struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
472 	char *end_of_acl = ((char *)pntsd) + acl_len;
473 	__u32 dacloffset;
474 
475 	if ((inode == NULL) || (pntsd == NULL))
476 		return -EIO;
477 
478 	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
479 				le32_to_cpu(pntsd->osidoffset));
480 	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
481 				le32_to_cpu(pntsd->gsidoffset));
482 	dacloffset = le32_to_cpu(pntsd->dacloffset);
483 	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
484 	cFYI(DBG2, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
485 		 "sacloffset 0x%x dacloffset 0x%x",
486 		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
487 		 le32_to_cpu(pntsd->gsidoffset),
488 		 le32_to_cpu(pntsd->sacloffset), dacloffset));
489 /*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
490 	rc = parse_sid(owner_sid_ptr, end_of_acl);
491 	if (rc)
492 		return rc;
493 
494 	rc = parse_sid(group_sid_ptr, end_of_acl);
495 	if (rc)
496 		return rc;
497 
498 	if (dacloffset)
499 		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
500 			   group_sid_ptr, inode);
501 	else
502 		cFYI(1, ("no ACL")); /* BB grant all or default perms? */
503 
504 /*	cifscred->uid = owner_sid_ptr->rid;
505 	cifscred->gid = group_sid_ptr->rid;
506 	memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
507 			sizeof(struct cifs_sid));
508 	memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
509 			sizeof(struct cifs_sid)); */
510 
511 
512 	return 0;
513 }
514 
515 
516 /* Convert permission bits from mode to equivalent CIFS ACL */
build_sec_desc(struct cifs_ntsd * pntsd,struct cifs_ntsd * pnntsd,struct inode * inode,__u64 nmode)517 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
518 				struct inode *inode, __u64 nmode)
519 {
520 	int rc = 0;
521 	__u32 dacloffset;
522 	__u32 ndacloffset;
523 	__u32 sidsoffset;
524 	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
525 	struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
526 	struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
527 
528 	if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
529 		return -EIO;
530 
531 	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
532 				le32_to_cpu(pntsd->osidoffset));
533 	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
534 				le32_to_cpu(pntsd->gsidoffset));
535 
536 	dacloffset = le32_to_cpu(pntsd->dacloffset);
537 	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
538 
539 	ndacloffset = sizeof(struct cifs_ntsd);
540 	ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
541 	ndacl_ptr->revision = dacl_ptr->revision;
542 	ndacl_ptr->size = 0;
543 	ndacl_ptr->num_aces = 0;
544 
545 	rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
546 
547 	sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
548 
549 	/* copy security descriptor control portion and owner and group sid */
550 	copy_sec_desc(pntsd, pnntsd, sidsoffset);
551 
552 	return rc;
553 }
554 
555 
556 /* Retrieve an ACL from the server */
get_cifs_acl(u32 * pacllen,struct inode * inode,const char * path,const __u16 * pfid)557 static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
558 				       const char *path, const __u16 *pfid)
559 {
560 	struct cifsFileInfo *open_file = NULL;
561 	bool unlock_file = false;
562 	int xid;
563 	int rc = -EIO;
564 	__u16 fid;
565 	struct super_block *sb;
566 	struct cifs_sb_info *cifs_sb;
567 	struct cifs_ntsd *pntsd = NULL;
568 
569 	cFYI(1, ("get mode from ACL for %s", path));
570 
571 	if (inode == NULL)
572 		return NULL;
573 
574 	xid = GetXid();
575 	if (pfid == NULL)
576 		open_file = find_readable_file(CIFS_I(inode));
577 	else
578 		fid = *pfid;
579 
580 	sb = inode->i_sb;
581 	if (sb == NULL) {
582 		FreeXid(xid);
583 		return NULL;
584 	}
585 	cifs_sb = CIFS_SB(sb);
586 
587 	if (open_file) {
588 		unlock_file = true;
589 		fid = open_file->netfid;
590 	} else if (pfid == NULL) {
591 		int oplock = 0;
592 		/* open file */
593 		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
594 				READ_CONTROL, 0, &fid, &oplock, NULL,
595 				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
596 					CIFS_MOUNT_MAP_SPECIAL_CHR);
597 		if (rc != 0) {
598 			cERROR(1, ("Unable to open file to get ACL"));
599 			FreeXid(xid);
600 			return NULL;
601 		}
602 	}
603 
604 	rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
605 	cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
606 	if (unlock_file == true) /* find_readable_file increments ref count */
607 		atomic_dec(&open_file->wrtPending);
608 	else if (pfid == NULL) /* if opened above we have to close the handle */
609 		CIFSSMBClose(xid, cifs_sb->tcon, fid);
610 	/* else handle was passed in by caller */
611 
612 	FreeXid(xid);
613 	return pntsd;
614 }
615 
616 /* Set an ACL on the server */
set_cifs_acl(struct cifs_ntsd * pnntsd,__u32 acllen,struct inode * inode,const char * path)617 static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
618 				struct inode *inode, const char *path)
619 {
620 	struct cifsFileInfo *open_file;
621 	bool unlock_file = false;
622 	int xid;
623 	int rc = -EIO;
624 	__u16 fid;
625 	struct super_block *sb;
626 	struct cifs_sb_info *cifs_sb;
627 
628 	cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
629 
630 	if (!inode)
631 		return rc;
632 
633 	sb = inode->i_sb;
634 	if (sb == NULL)
635 		return rc;
636 
637 	cifs_sb = CIFS_SB(sb);
638 	xid = GetXid();
639 
640 	open_file = find_readable_file(CIFS_I(inode));
641 	if (open_file) {
642 		unlock_file = true;
643 		fid = open_file->netfid;
644 	} else {
645 		int oplock = 0;
646 		/* open file */
647 		rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
648 				WRITE_DAC, 0, &fid, &oplock, NULL,
649 				cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
650 					CIFS_MOUNT_MAP_SPECIAL_CHR);
651 		if (rc != 0) {
652 			cERROR(1, ("Unable to open file to set ACL"));
653 			FreeXid(xid);
654 			return rc;
655 		}
656 	}
657 
658 	rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
659 	cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
660 	if (unlock_file)
661 		atomic_dec(&open_file->wrtPending);
662 	else
663 		CIFSSMBClose(xid, cifs_sb->tcon, fid);
664 
665 	FreeXid(xid);
666 
667 	return rc;
668 }
669 
670 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
acl_to_uid_mode(struct inode * inode,const char * path,const __u16 * pfid)671 void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
672 {
673 	struct cifs_ntsd *pntsd = NULL;
674 	u32 acllen = 0;
675 	int rc = 0;
676 
677 	cFYI(DBG2, ("converting ACL to mode for %s", path));
678 	pntsd = get_cifs_acl(&acllen, inode, path, pfid);
679 
680 	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
681 	if (pntsd)
682 		rc = parse_sec_desc(pntsd, acllen, inode);
683 	if (rc)
684 		cFYI(1, ("parse sec desc failed rc = %d", rc));
685 
686 	kfree(pntsd);
687 	return;
688 }
689 
690 /* Convert mode bits to an ACL so we can update the ACL on the server */
mode_to_acl(struct inode * inode,const char * path,__u64 nmode)691 int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
692 {
693 	int rc = 0;
694 	__u32 secdesclen = 0;
695 	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
696 	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
697 
698 	cFYI(DBG2, ("set ACL from mode for %s", path));
699 
700 	/* Get the security descriptor */
701 	pntsd = get_cifs_acl(&secdesclen, inode, path, NULL);
702 
703 	/* Add three ACEs for owner, group, everyone getting rid of
704 	   other ACEs as chmod disables ACEs and set the security descriptor */
705 
706 	if (pntsd) {
707 		/* allocate memory for the smb header,
708 		   set security descriptor request security descriptor
709 		   parameters, and secuirty descriptor itself */
710 
711 		secdesclen = secdesclen < DEFSECDESCLEN ?
712 					DEFSECDESCLEN : secdesclen;
713 		pnntsd = kmalloc(secdesclen, GFP_KERNEL);
714 		if (!pnntsd) {
715 			cERROR(1, ("Unable to allocate security descriptor"));
716 			kfree(pntsd);
717 			return -ENOMEM;
718 		}
719 
720 		rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
721 
722 		cFYI(DBG2, ("build_sec_desc rc: %d", rc));
723 
724 		if (!rc) {
725 			/* Set the security descriptor */
726 			rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
727 			cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
728 		}
729 
730 		kfree(pnntsd);
731 		kfree(pntsd);
732 	}
733 
734 	return rc;
735 }
736 #endif /* CONFIG_CIFS_EXPERIMENTAL */
737