blob: a437ec391a015fb7c05725543d6c118eadefc466 [file] [log] [blame]
Steve Frenchbcb02032007-09-25 16:17:24 +00001/*
2 * fs/cifs/cifsacl.c
3 *
Steve French8b1327f2008-03-14 22:37:16 +00004 * Copyright (C) International Business Machines Corp., 2007,2008
Steve Frenchbcb02032007-09-25 16:17:24 +00005 * 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
Steve French65874002007-09-25 19:53:44 +000024#include <linux/fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Steve French65874002007-09-25 19:53:44 +000026#include "cifspdu.h"
27#include "cifsglob.h"
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000028#include "cifsacl.h"
Steve French65874002007-09-25 19:53:44 +000029#include "cifsproto.h"
30#include "cifs_debug.h"
Steve French65874002007-09-25 19:53:44 +000031
Steve French297647c2007-10-12 04:11:59 +000032
Steve Frenchaf6f4612007-10-16 18:40:37 +000033static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
Steve French297647c2007-10-12 04:11:59 +000034 {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
35 {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
Jeff Layton536abdb2008-07-12 13:48:00 -070036 {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
37 {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
38 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"},
39 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"},
40 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} }
Steve French44093ca2007-10-23 21:22:55 +000041;
Steve French297647c2007-10-12 04:11:59 +000042
43
Steve Frenchbcb02032007-09-25 16:17:24 +000044/* security id for everyone */
Shirish Pargaonkare01b6402007-10-30 04:45:14 +000045static const struct cifs_sid sid_everyone = {
46 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
Steve Frenchbcb02032007-09-25 16:17:24 +000047/* group users */
Steve Frenchad7a2922008-02-07 23:25:02 +000048static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +000049
Steve French297647c2007-10-12 04:11:59 +000050
51int match_sid(struct cifs_sid *ctsid)
52{
53 int i, j;
54 int num_subauth, num_sat, num_saw;
55 struct cifs_sid *cwsid;
56
57 if (!ctsid)
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +000058 return -1;
Steve French297647c2007-10-12 04:11:59 +000059
60 for (i = 0; i < NUM_WK_SIDS; ++i) {
61 cwsid = &(wksidarr[i].cifssid);
62
63 /* compare the revision */
64 if (ctsid->revision != cwsid->revision)
65 continue;
66
67 /* compare all of the six auth values */
68 for (j = 0; j < 6; ++j) {
69 if (ctsid->authority[j] != cwsid->authority[j])
70 break;
71 }
72 if (j < 6)
73 continue; /* all of the auth values did not match */
74
75 /* compare all of the subauth values if any */
Dave Kleikampce51ae12007-10-16 21:35:39 +000076 num_sat = ctsid->num_subauth;
77 num_saw = cwsid->num_subauth;
Steve French297647c2007-10-12 04:11:59 +000078 num_subauth = num_sat < num_saw ? num_sat : num_saw;
79 if (num_subauth) {
80 for (j = 0; j < num_subauth; ++j) {
81 if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
82 break;
83 }
84 if (j < num_subauth)
85 continue; /* all sub_auth values do not match */
86 }
87
Joe Perchesb6b38f72010-04-21 03:50:45 +000088 cFYI(1, "matching sid: %s\n", wksidarr[i].sidname);
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +000089 return 0; /* sids compare/match */
Steve French297647c2007-10-12 04:11:59 +000090 }
91
Joe Perchesb6b38f72010-04-21 03:50:45 +000092 cFYI(1, "No matching sid");
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +000093 return -1;
Steve French297647c2007-10-12 04:11:59 +000094}
95
Steve Frencha750e772007-10-17 22:50:39 +000096/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
97 the same returns 1, if they do not match returns 0 */
Steve French630f3f02007-10-25 21:17:17 +000098int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
Steve French297647c2007-10-12 04:11:59 +000099{
100 int i;
101 int num_subauth, num_sat, num_saw;
102
103 if ((!ctsid) || (!cwsid))
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000104 return 0;
Steve French297647c2007-10-12 04:11:59 +0000105
106 /* compare the revision */
107 if (ctsid->revision != cwsid->revision)
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000108 return 0;
Steve French297647c2007-10-12 04:11:59 +0000109
110 /* compare all of the six auth values */
111 for (i = 0; i < 6; ++i) {
112 if (ctsid->authority[i] != cwsid->authority[i])
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000113 return 0;
Steve French297647c2007-10-12 04:11:59 +0000114 }
115
116 /* compare all of the subauth values if any */
Steve Frenchadbc0352007-10-17 02:12:46 +0000117 num_sat = ctsid->num_subauth;
Steve Frenchadddd492007-10-17 02:48:17 +0000118 num_saw = cwsid->num_subauth;
Steve French297647c2007-10-12 04:11:59 +0000119 num_subauth = num_sat < num_saw ? num_sat : num_saw;
120 if (num_subauth) {
121 for (i = 0; i < num_subauth; ++i) {
122 if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000123 return 0;
Steve French297647c2007-10-12 04:11:59 +0000124 }
125 }
126
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000127 return 1; /* sids compare/match */
Steve French297647c2007-10-12 04:11:59 +0000128}
129
Steve French97837582007-12-31 07:47:21 +0000130
131/* copy ntsd, owner sid, and group sid from a security descriptor to another */
132static void copy_sec_desc(const struct cifs_ntsd *pntsd,
133 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
134{
135 int i;
136
137 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
138 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
139
140 /* copy security descriptor control portion */
141 pnntsd->revision = pntsd->revision;
142 pnntsd->type = pntsd->type;
143 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
144 pnntsd->sacloffset = 0;
145 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
146 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
147
148 /* copy owner sid */
149 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
150 le32_to_cpu(pntsd->osidoffset));
151 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
152
153 nowner_sid_ptr->revision = owner_sid_ptr->revision;
154 nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
155 for (i = 0; i < 6; i++)
156 nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
157 for (i = 0; i < 5; i++)
158 nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
159
160 /* copy group sid */
161 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
162 le32_to_cpu(pntsd->gsidoffset));
163 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
164 sizeof(struct cifs_sid));
165
166 ngroup_sid_ptr->revision = group_sid_ptr->revision;
167 ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
168 for (i = 0; i < 6; i++)
169 ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
170 for (i = 0; i < 5; i++)
Shirish Pargaonkarb1910ad2008-07-24 14:53:20 +0000171 ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
Steve French97837582007-12-31 07:47:21 +0000172
173 return;
174}
175
176
Steve French630f3f02007-10-25 21:17:17 +0000177/*
178 change posix mode to reflect permissions
179 pmode is the existing mode (we only want to overwrite part of this
180 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
181*/
Al Viro9b5e6852007-12-05 08:24:38 +0000182static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
Steve French15b03952007-11-08 17:57:40 +0000183 umode_t *pbits_to_set)
Steve French4879b442007-10-19 21:57:39 +0000184{
Al Viro9b5e6852007-12-05 08:24:38 +0000185 __u32 flags = le32_to_cpu(ace_flags);
Steve French15b03952007-11-08 17:57:40 +0000186 /* the order of ACEs is important. The canonical order is to begin with
Steve Frenchce06c9f2007-11-08 21:12:01 +0000187 DENY entries followed by ALLOW, otherwise an allow entry could be
Steve French15b03952007-11-08 17:57:40 +0000188 encountered first, making the subsequent deny entry like "dead code"
Steve Frenchce06c9f2007-11-08 21:12:01 +0000189 which would be superflous since Windows stops when a match is made
Steve French15b03952007-11-08 17:57:40 +0000190 for the operation you are trying to perform for your user */
191
192 /* For deny ACEs we change the mask so that subsequent allow access
193 control entries do not turn on the bits we are denying */
194 if (type == ACCESS_DENIED) {
Steve Frenchad7a2922008-02-07 23:25:02 +0000195 if (flags & GENERIC_ALL)
Steve French15b03952007-11-08 17:57:40 +0000196 *pbits_to_set &= ~S_IRWXUGO;
Steve Frenchad7a2922008-02-07 23:25:02 +0000197
Al Viro9b5e6852007-12-05 08:24:38 +0000198 if ((flags & GENERIC_WRITE) ||
199 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000200 *pbits_to_set &= ~S_IWUGO;
Al Viro9b5e6852007-12-05 08:24:38 +0000201 if ((flags & GENERIC_READ) ||
202 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000203 *pbits_to_set &= ~S_IRUGO;
Al Viro9b5e6852007-12-05 08:24:38 +0000204 if ((flags & GENERIC_EXECUTE) ||
205 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000206 *pbits_to_set &= ~S_IXUGO;
207 return;
208 } else if (type != ACCESS_ALLOWED) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000209 cERROR(1, "unknown access control type %d", type);
Steve French15b03952007-11-08 17:57:40 +0000210 return;
211 }
212 /* else ACCESS_ALLOWED type */
Steve French44093ca2007-10-23 21:22:55 +0000213
Al Viro9b5e6852007-12-05 08:24:38 +0000214 if (flags & GENERIC_ALL) {
Steve French15b03952007-11-08 17:57:40 +0000215 *pmode |= (S_IRWXUGO & (*pbits_to_set));
Joe Perchesb6b38f72010-04-21 03:50:45 +0000216 cFYI(DBG2, "all perms");
Steve Frenchd61e5802007-10-26 04:32:43 +0000217 return;
218 }
Al Viro9b5e6852007-12-05 08:24:38 +0000219 if ((flags & GENERIC_WRITE) ||
220 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000221 *pmode |= (S_IWUGO & (*pbits_to_set));
Al Viro9b5e6852007-12-05 08:24:38 +0000222 if ((flags & GENERIC_READ) ||
223 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000224 *pmode |= (S_IRUGO & (*pbits_to_set));
Al Viro9b5e6852007-12-05 08:24:38 +0000225 if ((flags & GENERIC_EXECUTE) ||
226 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
Steve French15b03952007-11-08 17:57:40 +0000227 *pmode |= (S_IXUGO & (*pbits_to_set));
Steve Frenchd61e5802007-10-26 04:32:43 +0000228
Joe Perchesb6b38f72010-04-21 03:50:45 +0000229 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
Steve French630f3f02007-10-25 21:17:17 +0000230 return;
231}
232
Steve Frenchce06c9f2007-11-08 21:12:01 +0000233/*
234 Generate access flags to reflect permissions mode is the existing mode.
235 This function is called for every ACE in the DACL whose SID matches
236 with either owner or group or everyone.
237*/
238
239static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
240 __u32 *pace_flags)
241{
242 /* reset access mask */
243 *pace_flags = 0x0;
244
245 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
246 mode &= bits_to_use;
247
248 /* check for R/W/X UGO since we do not know whose flags
249 is this but we have cleared all the bits sans RWX for
250 either user or group or other as per bits_to_use */
251 if (mode & S_IRUGO)
252 *pace_flags |= SET_FILE_READ_RIGHTS;
253 if (mode & S_IWUGO)
254 *pace_flags |= SET_FILE_WRITE_RIGHTS;
255 if (mode & S_IXUGO)
256 *pace_flags |= SET_FILE_EXEC_RIGHTS;
257
Joe Perchesb6b38f72010-04-21 03:50:45 +0000258 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
Steve Frenchce06c9f2007-11-08 21:12:01 +0000259 return;
260}
261
Al Viro2b210ad2008-03-29 03:09:18 +0000262static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
Steve French97837582007-12-31 07:47:21 +0000263 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
264{
265 int i;
266 __u16 size = 0;
267 __u32 access_req = 0;
268
269 pntace->type = ACCESS_ALLOWED;
270 pntace->flags = 0x0;
271 mode_to_access_flags(nmode, bits, &access_req);
272 if (!access_req)
273 access_req = SET_MINIMUM_RIGHTS;
274 pntace->access_req = cpu_to_le32(access_req);
275
276 pntace->sid.revision = psid->revision;
277 pntace->sid.num_subauth = psid->num_subauth;
278 for (i = 0; i < 6; i++)
279 pntace->sid.authority[i] = psid->authority[i];
280 for (i = 0; i < psid->num_subauth; i++)
281 pntace->sid.sub_auth[i] = psid->sub_auth[i];
282
283 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
284 pntace->size = cpu_to_le16(size);
285
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000286 return size;
Steve French97837582007-12-31 07:47:21 +0000287}
288
Steve French297647c2007-10-12 04:11:59 +0000289
Steve French953f8682007-10-31 04:54:42 +0000290#ifdef CONFIG_CIFS_DEBUG2
291static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000292{
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000293 int num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000294
295 /* validate that we do not go past end of acl */
Steve French297647c2007-10-12 04:11:59 +0000296
Steve French44093ca2007-10-23 21:22:55 +0000297 if (le16_to_cpu(pace->size) < 16) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000298 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
Steve French44093ca2007-10-23 21:22:55 +0000299 return;
300 }
301
302 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000303 cERROR(1, "ACL too small to parse ACE");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000304 return;
Steve French44093ca2007-10-23 21:22:55 +0000305 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000306
Steve French44093ca2007-10-23 21:22:55 +0000307 num_subauth = pace->sid.num_subauth;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000308 if (num_subauth) {
Steve French8f18c132007-10-12 18:54:12 +0000309 int i;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000310 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
Steve French44093ca2007-10-23 21:22:55 +0000311 pace->sid.revision, pace->sid.num_subauth, pace->type,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000312 pace->flags, le16_to_cpu(pace->size));
Steve Frenchd12fd122007-10-03 19:43:19 +0000313 for (i = 0; i < num_subauth; ++i) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000314 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
315 le32_to_cpu(pace->sid.sub_auth[i]));
Steve Frenchd12fd122007-10-03 19:43:19 +0000316 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000317
Steve Frenchd12fd122007-10-03 19:43:19 +0000318 /* BB add length check to make sure that we do not have huge
319 num auths and therefore go off the end */
Steve Frenchd12fd122007-10-03 19:43:19 +0000320 }
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000321
Steve Frenchd12fd122007-10-03 19:43:19 +0000322 return;
323}
Steve French953f8682007-10-31 04:54:42 +0000324#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000325
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000326
Steve Frencha750e772007-10-17 22:50:39 +0000327static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
Steve Frenchd61e5802007-10-26 04:32:43 +0000328 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400329 struct cifs_fattr *fattr)
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000330{
331 int i;
332 int num_aces = 0;
333 int acl_size;
334 char *acl_base;
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000335 struct cifs_ace **ppace;
336
337 /* BB need to add parm so we can store the SID BB */
338
Steve French2b834572007-11-25 10:01:00 +0000339 if (!pdacl) {
340 /* no DACL in the security descriptor, set
341 all the permissions for user/group/other */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400342 fattr->cf_mode |= S_IRWXUGO;
Steve French2b834572007-11-25 10:01:00 +0000343 return;
344 }
345
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000346 /* validate that we do not go past end of acl */
Steve Frenchaf6f4612007-10-16 18:40:37 +0000347 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000348 cERROR(1, "ACL too small to parse DACL");
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000349 return;
350 }
351
Joe Perchesb6b38f72010-04-21 03:50:45 +0000352 cFYI(DBG2, "DACL revision %d size %d num aces %d",
Steve Frenchaf6f4612007-10-16 18:40:37 +0000353 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
Joe Perchesb6b38f72010-04-21 03:50:45 +0000354 le32_to_cpu(pdacl->num_aces));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000355
Steve French7505e052007-11-01 18:03:01 +0000356 /* reset rwx permissions for user/group/other.
357 Also, if num_aces is 0 i.e. DACL has no ACEs,
358 user/group/other have no permissions */
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400359 fattr->cf_mode &= ~(S_IRWXUGO);
Steve French7505e052007-11-01 18:03:01 +0000360
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000361 acl_base = (char *)pdacl;
362 acl_size = sizeof(struct cifs_acl);
363
Steve Frenchadbc0352007-10-17 02:12:46 +0000364 num_aces = le32_to_cpu(pdacl->num_aces);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000365 if (num_aces > 0) {
Steve French15b03952007-11-08 17:57:40 +0000366 umode_t user_mask = S_IRWXU;
367 umode_t group_mask = S_IRWXG;
368 umode_t other_mask = S_IRWXO;
369
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000370 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
371 GFP_KERNEL);
372
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000373 for (i = 0; i < num_aces; ++i) {
Steve French44093ca2007-10-23 21:22:55 +0000374 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
Steve French953f8682007-10-31 04:54:42 +0000375#ifdef CONFIG_CIFS_DEBUG2
376 dump_ace(ppace[i], end_of_acl);
377#endif
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000378 if (compare_sids(&(ppace[i]->sid), pownersid))
379 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000380 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400381 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000382 &user_mask);
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000383 if (compare_sids(&(ppace[i]->sid), pgrpsid))
384 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000385 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400386 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000387 &group_mask);
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000388 if (compare_sids(&(ppace[i]->sid), &sid_everyone))
389 access_flags_to_mode(ppace[i]->access_req,
Steve French15b03952007-11-08 17:57:40 +0000390 ppace[i]->type,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400391 &fattr->cf_mode,
Steve French15b03952007-11-08 17:57:40 +0000392 &other_mask);
Shirish Pargaonkare01b6402007-10-30 04:45:14 +0000393
Steve French44093ca2007-10-23 21:22:55 +0000394/* memcpy((void *)(&(cifscred->aces[i])),
Steve Frenchd12fd122007-10-03 19:43:19 +0000395 (void *)ppace[i],
396 sizeof(struct cifs_ace)); */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000397
Steve French44093ca2007-10-23 21:22:55 +0000398 acl_base = (char *)ppace[i];
399 acl_size = le16_to_cpu(ppace[i]->size);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000400 }
401
402 kfree(ppace);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000403 }
404
405 return;
406}
407
Steve Frenchbcb02032007-09-25 16:17:24 +0000408
Steve French97837582007-12-31 07:47:21 +0000409static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
410 struct cifs_sid *pgrpsid, __u64 nmode)
411{
Al Viro2b210ad2008-03-29 03:09:18 +0000412 u16 size = 0;
Steve French97837582007-12-31 07:47:21 +0000413 struct cifs_acl *pnndacl;
414
415 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
416
417 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
418 pownersid, nmode, S_IRWXU);
419 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
420 pgrpsid, nmode, S_IRWXG);
421 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
422 &sid_everyone, nmode, S_IRWXO);
423
424 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
Shirish Pargaonkard9f382e2008-02-12 20:46:26 +0000425 pndacl->num_aces = cpu_to_le32(3);
Steve French97837582007-12-31 07:47:21 +0000426
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000427 return 0;
Steve French97837582007-12-31 07:47:21 +0000428}
429
430
Steve Frenchbcb02032007-09-25 16:17:24 +0000431static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
432{
433 /* BB need to add parm so we can store the SID BB */
434
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000435 /* validate that we do not go past end of ACL - sid must be at least 8
436 bytes long (assuming no sub-auths - e.g. the null SID */
437 if (end_of_acl < (char *)psid + 8) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000438 cERROR(1, "ACL too small to parse SID %p", psid);
Steve Frenchbcb02032007-09-25 16:17:24 +0000439 return -EINVAL;
440 }
Steve Frenchbcb02032007-09-25 16:17:24 +0000441
Steve Frenchaf6f4612007-10-16 18:40:37 +0000442 if (psid->num_subauth) {
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000443#ifdef CONFIG_CIFS_DEBUG2
Steve French8f18c132007-10-12 18:54:12 +0000444 int i;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000445 cFYI(1, "SID revision %d num_auth %d",
446 psid->revision, psid->num_subauth);
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000447
Steve Frenchaf6f4612007-10-16 18:40:37 +0000448 for (i = 0; i < psid->num_subauth; i++) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000449 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
450 le32_to_cpu(psid->sub_auth[i]));
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000451 }
452
Steve Frenchd12fd122007-10-03 19:43:19 +0000453 /* BB add length check to make sure that we do not have huge
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000454 num auths and therefore go off the end */
Joe Perchesb6b38f72010-04-21 03:50:45 +0000455 cFYI(1, "RID 0x%x",
456 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
Steve Frenchbcb02032007-09-25 16:17:24 +0000457#endif
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000458 }
459
Steve Frenchbcb02032007-09-25 16:17:24 +0000460 return 0;
461}
462
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000463
Steve Frenchbcb02032007-09-25 16:17:24 +0000464/* Convert CIFS ACL to POSIX form */
Steve French630f3f02007-10-25 21:17:17 +0000465static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400466 struct cifs_fattr *fattr)
Steve Frenchbcb02032007-09-25 16:17:24 +0000467{
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000468 int rc;
Steve Frenchbcb02032007-09-25 16:17:24 +0000469 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
470 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
Steve Frenchbcb02032007-09-25 16:17:24 +0000471 char *end_of_acl = ((char *)pntsd) + acl_len;
Steve French7505e052007-11-01 18:03:01 +0000472 __u32 dacloffset;
Steve Frenchbcb02032007-09-25 16:17:24 +0000473
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400474 if (pntsd == NULL)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000475 return -EIO;
476
Steve Frenchbcb02032007-09-25 16:17:24 +0000477 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +0000478 le32_to_cpu(pntsd->osidoffset));
Steve Frenchbcb02032007-09-25 16:17:24 +0000479 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
Steve Frenchaf6f4612007-10-16 18:40:37 +0000480 le32_to_cpu(pntsd->gsidoffset));
Steve French7505e052007-11-01 18:03:01 +0000481 dacloffset = le32_to_cpu(pntsd->dacloffset);
Steve French63d25832007-11-05 21:46:10 +0000482 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000483 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
Steve Frenchbcb02032007-09-25 16:17:24 +0000484 "sacloffset 0x%x dacloffset 0x%x",
Steve Frenchaf6f4612007-10-16 18:40:37 +0000485 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
486 le32_to_cpu(pntsd->gsidoffset),
Joe Perchesb6b38f72010-04-21 03:50:45 +0000487 le32_to_cpu(pntsd->sacloffset), dacloffset);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000488/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
Steve Frenchbcb02032007-09-25 16:17:24 +0000489 rc = parse_sid(owner_sid_ptr, end_of_acl);
490 if (rc)
491 return rc;
492
493 rc = parse_sid(group_sid_ptr, end_of_acl);
494 if (rc)
495 return rc;
496
Steve French7505e052007-11-01 18:03:01 +0000497 if (dacloffset)
498 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400499 group_sid_ptr, fattr);
Steve French7505e052007-11-01 18:03:01 +0000500 else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000501 cFYI(1, "no ACL"); /* BB grant all or default perms? */
Shirish Pargaonkard0d66c42007-10-03 18:22:19 +0000502
Steve Frenchbcb02032007-09-25 16:17:24 +0000503/* cifscred->uid = owner_sid_ptr->rid;
504 cifscred->gid = group_sid_ptr->rid;
505 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
Steve French630f3f02007-10-25 21:17:17 +0000506 sizeof(struct cifs_sid));
Steve Frenchbcb02032007-09-25 16:17:24 +0000507 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
Steve French630f3f02007-10-25 21:17:17 +0000508 sizeof(struct cifs_sid)); */
Steve Frenchbcb02032007-09-25 16:17:24 +0000509
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000510 return 0;
Steve Frenchbcb02032007-09-25 16:17:24 +0000511}
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000512
513
Steve French97837582007-12-31 07:47:21 +0000514/* Convert permission bits from mode to equivalent CIFS ACL */
515static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
Steve Frenchcce246e2008-04-09 20:55:31 +0000516 struct inode *inode, __u64 nmode)
Steve French97837582007-12-31 07:47:21 +0000517{
518 int rc = 0;
519 __u32 dacloffset;
520 __u32 ndacloffset;
521 __u32 sidsoffset;
522 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
523 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
524 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
525
526 if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000527 return -EIO;
Steve French97837582007-12-31 07:47:21 +0000528
529 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
530 le32_to_cpu(pntsd->osidoffset));
531 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
532 le32_to_cpu(pntsd->gsidoffset));
533
534 dacloffset = le32_to_cpu(pntsd->dacloffset);
535 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
536
537 ndacloffset = sizeof(struct cifs_ntsd);
538 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
539 ndacl_ptr->revision = dacl_ptr->revision;
540 ndacl_ptr->size = 0;
541 ndacl_ptr->num_aces = 0;
542
543 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
544
545 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
546
547 /* copy security descriptor control portion and owner and group sid */
548 copy_sec_desc(pntsd, pnntsd, sidsoffset);
549
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000550 return rc;
Steve French97837582007-12-31 07:47:21 +0000551}
552
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400553static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
554 __u16 fid, u32 *pacllen)
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000555{
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000556 struct cifs_ntsd *pntsd = NULL;
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400557 int xid, rc;
Jeff Layton7ffec372010-09-29 19:51:11 -0400558 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
559
560 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600561 return ERR_CAST(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000562
563 xid = GetXid();
Jeff Layton7ffec372010-09-29 19:51:11 -0400564 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400565 FreeXid(xid);
Steve French8b1327f2008-03-14 22:37:16 +0000566
Jeff Layton7ffec372010-09-29 19:51:11 -0400567 cifs_put_tlink(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000568
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600569 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
570 if (rc)
571 return ERR_PTR(rc);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400572 return pntsd;
573}
574
575static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
576 const char *path, u32 *pacllen)
577{
578 struct cifs_ntsd *pntsd = NULL;
579 int oplock = 0;
580 int xid, rc;
581 __u16 fid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400582 struct cifsTconInfo *tcon;
583 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400584
Jeff Layton7ffec372010-09-29 19:51:11 -0400585 if (IS_ERR(tlink))
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600586 return ERR_CAST(tlink);
Jeff Layton7ffec372010-09-29 19:51:11 -0400587
588 tcon = tlink_tcon(tlink);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400589 xid = GetXid();
590
Jeff Layton7ffec372010-09-29 19:51:11 -0400591 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400592 &fid, &oplock, NULL, cifs_sb->local_nls,
593 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600594 if (!rc) {
595 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
596 CIFSSMBClose(xid, tcon, fid);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000597 }
598
Jeff Layton7ffec372010-09-29 19:51:11 -0400599 cifs_put_tlink(tlink);
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000600 FreeXid(xid);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600601
602 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
603 if (rc)
604 return ERR_PTR(rc);
Steve French7505e052007-11-01 18:03:01 +0000605 return pntsd;
606}
607
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400608/* Retrieve an ACL from the server */
Shirish Pargaonkarfbeba8b2010-11-27 11:37:54 -0600609struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400610 struct inode *inode, const char *path,
611 u32 *pacllen)
612{
613 struct cifs_ntsd *pntsd = NULL;
614 struct cifsFileInfo *open_file = NULL;
615
616 if (inode)
Jeff Layton6508d902010-09-29 19:51:11 -0400617 open_file = find_readable_file(CIFS_I(inode), true);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400618 if (!open_file)
619 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
620
621 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -0400622 cifsFileInfo_put(open_file);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400623 return pntsd;
624}
625
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400626static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
627 struct cifs_ntsd *pnntsd, u32 acllen)
Steve French97837582007-12-31 07:47:21 +0000628{
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400629 int xid, rc;
Jeff Layton7ffec372010-09-29 19:51:11 -0400630 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
631
632 if (IS_ERR(tlink))
633 return PTR_ERR(tlink);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400634
635 xid = GetXid();
Jeff Layton7ffec372010-09-29 19:51:11 -0400636 rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400637 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400638 cifs_put_tlink(tlink);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400639
Joe Perchesb6b38f72010-04-21 03:50:45 +0000640 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400641 return rc;
642}
643
644static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
645 struct cifs_ntsd *pnntsd, u32 acllen)
646{
647 int oplock = 0;
648 int xid, rc;
Steve French97837582007-12-31 07:47:21 +0000649 __u16 fid;
Jeff Layton7ffec372010-09-29 19:51:11 -0400650 struct cifsTconInfo *tcon;
651 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
Steve French97837582007-12-31 07:47:21 +0000652
Jeff Layton7ffec372010-09-29 19:51:11 -0400653 if (IS_ERR(tlink))
654 return PTR_ERR(tlink);
655
656 tcon = tlink_tcon(tlink);
Steve French97837582007-12-31 07:47:21 +0000657 xid = GetXid();
658
Jeff Layton7ffec372010-09-29 19:51:11 -0400659 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400660 &fid, &oplock, NULL, cifs_sb->local_nls,
661 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
662 if (rc) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000663 cERROR(1, "Unable to open file to set ACL");
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400664 goto out;
Steve French97837582007-12-31 07:47:21 +0000665 }
666
Jeff Layton7ffec372010-09-29 19:51:11 -0400667 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000668 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
Steve French97837582007-12-31 07:47:21 +0000669
Jeff Layton7ffec372010-09-29 19:51:11 -0400670 CIFSSMBClose(xid, tcon, fid);
671out:
Steve French97837582007-12-31 07:47:21 +0000672 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400673 cifs_put_tlink(tlink);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400674 return rc;
675}
Steve French97837582007-12-31 07:47:21 +0000676
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400677/* Set an ACL on the server */
678static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
679 struct inode *inode, const char *path)
680{
681 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
682 struct cifsFileInfo *open_file;
683 int rc;
684
Joe Perchesb6b38f72010-04-21 03:50:45 +0000685 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400686
Jeff Layton6508d902010-09-29 19:51:11 -0400687 open_file = find_readable_file(CIFS_I(inode), true);
Christoph Hellwigb96d31a2009-05-27 09:37:33 -0400688 if (!open_file)
689 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
690
691 rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
Dave Kleikamp6ab409b2009-08-31 11:07:12 -0400692 cifsFileInfo_put(open_file);
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000693 return rc;
Steve French97837582007-12-31 07:47:21 +0000694}
695
Steve French7505e052007-11-01 18:03:01 +0000696/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600697int
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400698cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
699 struct inode *inode, const char *path, const __u16 *pfid)
Steve French7505e052007-11-01 18:03:01 +0000700{
701 struct cifs_ntsd *pntsd = NULL;
702 u32 acllen = 0;
703 int rc = 0;
704
Joe Perchesb6b38f72010-04-21 03:50:45 +0000705 cFYI(DBG2, "converting ACL to mode for %s", path);
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400706
707 if (pfid)
708 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
709 else
710 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
Steve French7505e052007-11-01 18:03:01 +0000711
712 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600713 if (IS_ERR(pntsd)) {
714 rc = PTR_ERR(pntsd);
715 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
716 } else {
Jeff Layton0b8f18e2009-07-09 01:46:37 -0400717 rc = parse_sec_desc(pntsd, acllen, fattr);
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600718 kfree(pntsd);
719 if (rc)
720 cERROR(1, "parse sec desc failed rc = %d", rc);
721 }
Steve French7505e052007-11-01 18:03:01 +0000722
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600723 return rc;
Steve Frenchb9c7a2b2007-10-26 23:40:20 +0000724}
Steve French953f8682007-10-31 04:54:42 +0000725
Steve French7505e052007-11-01 18:03:01 +0000726/* Convert mode bits to an ACL so we can update the ACL on the server */
Shirish Pargaonkar78415d22010-11-27 11:37:26 -0600727int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
Steve French953f8682007-10-31 04:54:42 +0000728{
729 int rc = 0;
Steve Frenchcce246e2008-04-09 20:55:31 +0000730 __u32 secdesclen = 0;
Steve French97837582007-12-31 07:47:21 +0000731 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
732 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
Steve French953f8682007-10-31 04:54:42 +0000733
Joe Perchesb6b38f72010-04-21 03:50:45 +0000734 cFYI(DBG2, "set ACL from mode for %s", path);
Steve French953f8682007-10-31 04:54:42 +0000735
736 /* Get the security descriptor */
Christoph Hellwig1bf40722009-05-27 09:37:33 -0400737 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
Steve French953f8682007-10-31 04:54:42 +0000738
Steve French97837582007-12-31 07:47:21 +0000739 /* Add three ACEs for owner, group, everyone getting rid of
740 other ACEs as chmod disables ACEs and set the security descriptor */
Steve French953f8682007-10-31 04:54:42 +0000741
Shirish Pargaonkar987b21d2010-11-10 07:50:35 -0600742 if (IS_ERR(pntsd)) {
743 rc = PTR_ERR(pntsd);
744 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
745 } else {
Steve French97837582007-12-31 07:47:21 +0000746 /* allocate memory for the smb header,
747 set security descriptor request security descriptor
748 parameters, and secuirty descriptor itself */
Steve French953f8682007-10-31 04:54:42 +0000749
Steve Frenchcce246e2008-04-09 20:55:31 +0000750 secdesclen = secdesclen < DEFSECDESCLEN ?
751 DEFSECDESCLEN : secdesclen;
752 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
Steve French97837582007-12-31 07:47:21 +0000753 if (!pnntsd) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000754 cERROR(1, "Unable to allocate security descriptor");
Steve French97837582007-12-31 07:47:21 +0000755 kfree(pntsd);
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000756 return -ENOMEM;
Steve French97837582007-12-31 07:47:21 +0000757 }
Steve French7505e052007-11-01 18:03:01 +0000758
Steve Frenchcce246e2008-04-09 20:55:31 +0000759 rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
Steve French97837582007-12-31 07:47:21 +0000760
Joe Perchesb6b38f72010-04-21 03:50:45 +0000761 cFYI(DBG2, "build_sec_desc rc: %d", rc);
Steve French97837582007-12-31 07:47:21 +0000762
763 if (!rc) {
764 /* Set the security descriptor */
Steve Frenchcce246e2008-04-09 20:55:31 +0000765 rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000766 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
Steve French97837582007-12-31 07:47:21 +0000767 }
768
769 kfree(pnntsd);
770 kfree(pntsd);
771 }
772
Shirish Pargaonkaref571ca2008-07-24 15:56:05 +0000773 return rc;
Steve French953f8682007-10-31 04:54:42 +0000774}