fix "disabling echoes and oplocks" on SMB2 mounts
[linux-2.6-block.git] / fs / cifs / cifsacl.c
CommitLineData
bcb02034
SF
1/*
2 * fs/cifs/cifsacl.c
3 *
8b1327f6 4 * Copyright (C) International Business Machines Corp., 2007,2008
bcb02034
SF
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 24#include <linux/fs.h>
5a0e3ad6 25#include <linux/slab.h>
4d79dba0
SP
26#include <linux/string.h>
27#include <linux/keyctl.h>
28#include <linux/key-type.h>
29#include <keys/user-type.h>
65874007
SF
30#include "cifspdu.h"
31#include "cifsglob.h"
d0d66c44 32#include "cifsacl.h"
65874007
SF
33#include "cifsproto.h"
34#include "cifs_debug.h"
65874007 35
2fbc2f17 36/* security id for everyone/world system group */
e01b6400
SP
37static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
2fbc2f17
SP
39/* security id for Authenticated Users system group */
40static const struct cifs_sid sid_authusers = {
4f61258f 41 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
bcb02034 42/* group users */
ad7a2926 43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
d0d66c44 44
b1a6dc21 45static const struct cred *root_cred;
9409ae58 46
4d79dba0 47static int
cf7f601c 48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
4d79dba0
SP
49{
50 char *payload;
51
41a9f1f6
JL
52 /*
53 * If the payload is less than or equal to the size of a pointer, then
54 * an allocation here is wasteful. Just copy the data directly to the
55 * payload.value union member instead.
56 *
57 * With this however, you must check the datalen before trying to
58 * dereference payload.data!
59 */
1f630680 60 if (prep->datalen <= sizeof(key->payload)) {
41a9f1f6
JL
61 key->payload.value = 0;
62 memcpy(&key->payload.value, prep->data, prep->datalen);
63 key->datalen = prep->datalen;
64 return 0;
65 }
cf7f601c 66 payload = kmalloc(prep->datalen, GFP_KERNEL);
4d79dba0
SP
67 if (!payload)
68 return -ENOMEM;
69
cf7f601c 70 memcpy(payload, prep->data, prep->datalen);
4d79dba0 71 key->payload.data = payload;
cf7f601c 72 key->datalen = prep->datalen;
4d79dba0
SP
73 return 0;
74}
75
76static inline void
77cifs_idmap_key_destroy(struct key *key)
78{
1f630680 79 if (key->datalen > sizeof(key->payload))
41a9f1f6 80 kfree(key->payload.data);
4d79dba0
SP
81}
82
b1a6dc21 83static struct key_type cifs_idmap_key_type = {
c4aca0c0 84 .name = "cifs.idmap",
4d79dba0
SP
85 .instantiate = cifs_idmap_key_instantiate,
86 .destroy = cifs_idmap_key_destroy,
87 .describe = user_describe,
88 .match = user_match,
89};
90
faa65f07
JL
91static char *
92sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
9409ae58 93{
faa65f07 94 int i, len;
ee13b2ba 95 unsigned int saval;
faa65f07 96 char *sidstr, *strptr;
9409ae58 97
faa65f07
JL
98 /* 3 bytes for prefix */
99 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
100 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
101 GFP_KERNEL);
102 if (!sidstr)
103 return sidstr;
9409ae58 104
faa65f07
JL
105 strptr = sidstr;
106 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
107 sidptr->revision);
108 strptr += len;
9409ae58 109
852e2295 110 for (i = 0; i < NUM_AUTHS; ++i) {
9409ae58 111 if (sidptr->authority[i]) {
faa65f07
JL
112 len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
113 strptr += len;
9409ae58
SP
114 }
115 }
116
117 for (i = 0; i < sidptr->num_subauth; ++i) {
118 saval = le32_to_cpu(sidptr->sub_auth[i]);
faa65f07
JL
119 len = sprintf(strptr, "-%u", saval);
120 strptr += len;
9409ae58 121 }
faa65f07
JL
122
123 return sidstr;
9409ae58
SP
124}
125
436bb435
JL
126/*
127 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
128 * the same returns zero, if they do not match returns non-zero.
129 */
130static int
131compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
132{
133 int i;
134 int num_subauth, num_sat, num_saw;
135
136 if ((!ctsid) || (!cwsid))
137 return 1;
138
139 /* compare the revision */
140 if (ctsid->revision != cwsid->revision) {
141 if (ctsid->revision > cwsid->revision)
142 return 1;
143 else
144 return -1;
145 }
146
147 /* compare all of the six auth values */
148 for (i = 0; i < NUM_AUTHS; ++i) {
149 if (ctsid->authority[i] != cwsid->authority[i]) {
150 if (ctsid->authority[i] > cwsid->authority[i])
151 return 1;
152 else
153 return -1;
154 }
155 }
156
157 /* compare all of the subauth values if any */
158 num_sat = ctsid->num_subauth;
159 num_saw = cwsid->num_subauth;
160 num_subauth = num_sat < num_saw ? num_sat : num_saw;
161 if (num_subauth) {
162 for (i = 0; i < num_subauth; ++i) {
163 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
164 if (le32_to_cpu(ctsid->sub_auth[i]) >
165 le32_to_cpu(cwsid->sub_auth[i]))
166 return 1;
167 else
168 return -1;
169 }
170 }
171 }
172
173 return 0; /* sids compare/match */
174}
175
36960e44
JL
176static void
177cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
178{
36f87ee7
JL
179 int i;
180
181 dst->revision = src->revision;
30c9d6cc 182 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
36f87ee7
JL
183 for (i = 0; i < NUM_AUTHS; ++i)
184 dst->authority[i] = src->authority[i];
185 for (i = 0; i < dst->num_subauth; ++i)
186 dst->sub_auth[i] = src->sub_auth[i];
36960e44
JL
187}
188
9409ae58 189static int
faa65f07 190id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
9409ae58 191{
faa65f07 192 int rc;
21fed0d5 193 struct key *sidkey;
2ae03025
JL
194 struct cifs_sid *ksid;
195 unsigned int ksid_size;
faa65f07 196 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
21fed0d5 197 const struct cred *saved_cred;
21fed0d5 198
faa65f07
JL
199 rc = snprintf(desc, sizeof(desc), "%ci:%u",
200 sidtype == SIDOWNER ? 'o' : 'g', cid);
201 if (rc >= sizeof(desc))
202 return -EINVAL;
21fed0d5 203
faa65f07
JL
204 rc = 0;
205 saved_cred = override_creds(root_cred);
206 sidkey = request_key(&cifs_idmap_key_type, desc, "");
207 if (IS_ERR(sidkey)) {
21fed0d5 208 rc = -EINVAL;
faa65f07
JL
209 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
210 sidtype == SIDOWNER ? 'u' : 'g', cid);
211 goto out_revert_creds;
212 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
213 rc = -EIO;
214 cFYI(1, "%s: Downcall contained malformed key "
215 "(datalen=%hu)", __func__, sidkey->datalen);
2ae03025 216 goto invalidate_key;
21fed0d5 217 }
2ae03025 218
1f630680
JL
219 /*
220 * A sid is usually too large to be embedded in payload.value, but if
221 * there are no subauthorities and the host has 8-byte pointers, then
222 * it could be.
223 */
224 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
225 (struct cifs_sid *)&sidkey->payload.value :
226 (struct cifs_sid *)sidkey->payload.data;
227
2ae03025
JL
228 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
229 if (ksid_size > sidkey->datalen) {
230 rc = -EIO;
231 cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
232 "ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
233 goto invalidate_key;
234 }
1f630680 235
2ae03025 236 cifs_copy_sid(ssid, ksid);
faa65f07
JL
237out_key_put:
238 key_put(sidkey);
239out_revert_creds:
240 revert_creds(saved_cred);
21fed0d5 241 return rc;
2ae03025
JL
242
243invalidate_key:
244 key_invalidate(sidkey);
245 goto out_key_put;
21fed0d5
SP
246}
247
9409ae58
SP
248static int
249sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
250 struct cifs_fattr *fattr, uint sidtype)
251{
252 int rc;
faa65f07
JL
253 struct key *sidkey;
254 char *sidstr;
9409ae58 255 const struct cred *saved_cred;
faa65f07
JL
256 uid_t fuid = cifs_sb->mnt_uid;
257 gid_t fgid = cifs_sb->mnt_gid;
9409ae58
SP
258
259 /*
faa65f07
JL
260 * If we have too many subauthorities, then something is really wrong.
261 * Just return an error.
9409ae58 262 */
faa65f07
JL
263 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
264 cFYI(1, "%s: %u subauthorities is too many!", __func__,
265 psid->num_subauth);
266 return -EIO;
9409ae58
SP
267 }
268
faa65f07
JL
269 sidstr = sid_to_key_str(psid, sidtype);
270 if (!sidstr)
271 return -ENOMEM;
272
273 saved_cred = override_creds(root_cred);
274 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
275 if (IS_ERR(sidkey)) {
276 rc = -EINVAL;
277 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
278 sidtype == SIDOWNER ? 'u' : 'g');
279 goto out_revert_creds;
280 }
281
282 /*
283 * FIXME: Here we assume that uid_t and gid_t are same size. It's
284 * probably a safe assumption but might be better to check based on
285 * sidtype.
286 */
41a9f1f6 287 if (sidkey->datalen != sizeof(uid_t)) {
faa65f07
JL
288 rc = -EIO;
289 cFYI(1, "%s: Downcall contained malformed key "
290 "(datalen=%hu)", __func__, sidkey->datalen);
2ae03025 291 key_invalidate(sidkey);
faa65f07 292 goto out_key_put;
9409ae58
SP
293 }
294
9409ae58 295 if (sidtype == SIDOWNER)
41a9f1f6 296 memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
9409ae58 297 else
41a9f1f6 298 memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
faa65f07
JL
299
300out_key_put:
301 key_put(sidkey);
302out_revert_creds:
303 revert_creds(saved_cred);
304 kfree(sidstr);
9409ae58 305
faa65f07
JL
306 /*
307 * Note that we return 0 here unconditionally. If the mapping
308 * fails then we just fall back to using the mnt_uid/mnt_gid.
309 */
310 if (sidtype == SIDOWNER)
311 fattr->cf_uid = fuid;
312 else
313 fattr->cf_gid = fgid;
9409ae58
SP
314 return 0;
315}
316
4d79dba0
SP
317int
318init_cifs_idmap(void)
319{
320 struct cred *cred;
321 struct key *keyring;
322 int ret;
323
ac3aa2f8 324 cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
325
326 /* create an override credential set with a special thread keyring in
327 * which requests are cached
328 *
329 * this is used to prevent malicious redirections from being installed
330 * with add_key().
331 */
332 cred = prepare_kernel_cred(NULL);
333 if (!cred)
334 return -ENOMEM;
335
336 keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
337 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
338 KEY_USR_VIEW | KEY_USR_READ,
339 KEY_ALLOC_NOT_IN_QUOTA);
340 if (IS_ERR(keyring)) {
341 ret = PTR_ERR(keyring);
342 goto failed_put_cred;
343 }
344
345 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
346 if (ret < 0)
347 goto failed_put_key;
348
349 ret = register_key_type(&cifs_idmap_key_type);
350 if (ret < 0)
351 goto failed_put_key;
352
353 /* instruct request_key() to use this special keyring as a cache for
354 * the results it looks up */
700920eb 355 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
4d79dba0
SP
356 cred->thread_keyring = keyring;
357 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
358 root_cred = cred;
359
ac3aa2f8 360 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
4d79dba0
SP
361 return 0;
362
363failed_put_key:
364 key_put(keyring);
365failed_put_cred:
366 put_cred(cred);
367 return ret;
368}
369
370void
371exit_cifs_idmap(void)
372{
373 key_revoke(root_cred->thread_keyring);
374 unregister_key_type(&cifs_idmap_key_type);
375 put_cred(root_cred);
ac3aa2f8 376 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
4d79dba0
SP
377}
378
97837582
SF
379/* copy ntsd, owner sid, and group sid from a security descriptor to another */
380static void copy_sec_desc(const struct cifs_ntsd *pntsd,
381 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
382{
97837582
SF
383 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
384 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
385
386 /* copy security descriptor control portion */
387 pnntsd->revision = pntsd->revision;
388 pnntsd->type = pntsd->type;
389 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
390 pnntsd->sacloffset = 0;
391 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
392 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
393
394 /* copy owner sid */
395 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
396 le32_to_cpu(pntsd->osidoffset));
397 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
36960e44 398 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
97837582
SF
399
400 /* copy group sid */
401 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
402 le32_to_cpu(pntsd->gsidoffset));
403 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
404 sizeof(struct cifs_sid));
36960e44 405 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
97837582
SF
406
407 return;
408}
409
410
630f3f0c
SF
411/*
412 change posix mode to reflect permissions
413 pmode is the existing mode (we only want to overwrite part of this
414 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
415*/
9b5e6857 416static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
15b03959 417 umode_t *pbits_to_set)
630f3f0c 418{
9b5e6857 419 __u32 flags = le32_to_cpu(ace_flags);
15b03959 420 /* the order of ACEs is important. The canonical order is to begin with
ce06c9f0 421 DENY entries followed by ALLOW, otherwise an allow entry could be
15b03959 422 encountered first, making the subsequent deny entry like "dead code"
ce06c9f0 423 which would be superflous since Windows stops when a match is made
15b03959
SF
424 for the operation you are trying to perform for your user */
425
426 /* For deny ACEs we change the mask so that subsequent allow access
427 control entries do not turn on the bits we are denying */
428 if (type == ACCESS_DENIED) {
ad7a2926 429 if (flags & GENERIC_ALL)
15b03959 430 *pbits_to_set &= ~S_IRWXUGO;
ad7a2926 431
9b5e6857
AV
432 if ((flags & GENERIC_WRITE) ||
433 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 434 *pbits_to_set &= ~S_IWUGO;
9b5e6857
AV
435 if ((flags & GENERIC_READ) ||
436 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 437 *pbits_to_set &= ~S_IRUGO;
9b5e6857
AV
438 if ((flags & GENERIC_EXECUTE) ||
439 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959
SF
440 *pbits_to_set &= ~S_IXUGO;
441 return;
442 } else if (type != ACCESS_ALLOWED) {
b6b38f70 443 cERROR(1, "unknown access control type %d", type);
15b03959
SF
444 return;
445 }
446 /* else ACCESS_ALLOWED type */
630f3f0c 447
9b5e6857 448 if (flags & GENERIC_ALL) {
15b03959 449 *pmode |= (S_IRWXUGO & (*pbits_to_set));
b6b38f70 450 cFYI(DBG2, "all perms");
d61e5808
SF
451 return;
452 }
9b5e6857
AV
453 if ((flags & GENERIC_WRITE) ||
454 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
15b03959 455 *pmode |= (S_IWUGO & (*pbits_to_set));
9b5e6857
AV
456 if ((flags & GENERIC_READ) ||
457 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
15b03959 458 *pmode |= (S_IRUGO & (*pbits_to_set));
9b5e6857
AV
459 if ((flags & GENERIC_EXECUTE) ||
460 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
15b03959 461 *pmode |= (S_IXUGO & (*pbits_to_set));
630f3f0c 462
b6b38f70 463 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
630f3f0c
SF
464 return;
465}
466
ce06c9f0
SF
467/*
468 Generate access flags to reflect permissions mode is the existing mode.
469 This function is called for every ACE in the DACL whose SID matches
470 with either owner or group or everyone.
471*/
472
473static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
474 __u32 *pace_flags)
475{
476 /* reset access mask */
477 *pace_flags = 0x0;
478
479 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
480 mode &= bits_to_use;
481
482 /* check for R/W/X UGO since we do not know whose flags
483 is this but we have cleared all the bits sans RWX for
484 either user or group or other as per bits_to_use */
485 if (mode & S_IRUGO)
486 *pace_flags |= SET_FILE_READ_RIGHTS;
487 if (mode & S_IWUGO)
488 *pace_flags |= SET_FILE_WRITE_RIGHTS;
489 if (mode & S_IXUGO)
490 *pace_flags |= SET_FILE_EXEC_RIGHTS;
491
b6b38f70 492 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
ce06c9f0
SF
493 return;
494}
495
2b210adc 496static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
97837582
SF
497 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
498{
499 int i;
500 __u16 size = 0;
501 __u32 access_req = 0;
502
503 pntace->type = ACCESS_ALLOWED;
504 pntace->flags = 0x0;
505 mode_to_access_flags(nmode, bits, &access_req);
506 if (!access_req)
507 access_req = SET_MINIMUM_RIGHTS;
508 pntace->access_req = cpu_to_le32(access_req);
509
510 pntace->sid.revision = psid->revision;
511 pntace->sid.num_subauth = psid->num_subauth;
852e2295 512 for (i = 0; i < NUM_AUTHS; i++)
97837582
SF
513 pntace->sid.authority[i] = psid->authority[i];
514 for (i = 0; i < psid->num_subauth; i++)
515 pntace->sid.sub_auth[i] = psid->sub_auth[i];
516
517 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
518 pntace->size = cpu_to_le16(size);
519
ef571cad 520 return size;
97837582
SF
521}
522
297647c2 523
953f8681
SF
524#ifdef CONFIG_CIFS_DEBUG2
525static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
d0d66c44 526{
d0d66c44 527 int num_subauth;
d0d66c44
SP
528
529 /* validate that we do not go past end of acl */
297647c2 530
44093ca2 531 if (le16_to_cpu(pace->size) < 16) {
b6b38f70 532 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
44093ca2
SF
533 return;
534 }
535
536 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
b6b38f70 537 cERROR(1, "ACL too small to parse ACE");
d0d66c44 538 return;
44093ca2 539 }
d0d66c44 540
44093ca2 541 num_subauth = pace->sid.num_subauth;
d0d66c44 542 if (num_subauth) {
8f18c131 543 int i;
b6b38f70 544 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
44093ca2 545 pace->sid.revision, pace->sid.num_subauth, pace->type,
b6b38f70 546 pace->flags, le16_to_cpu(pace->size));
d12fd121 547 for (i = 0; i < num_subauth; ++i) {
b6b38f70
JP
548 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
549 le32_to_cpu(pace->sid.sub_auth[i]));
d12fd121
SF
550 }
551
552 /* BB add length check to make sure that we do not have huge
553 num auths and therefore go off the end */
d12fd121
SF
554 }
555
556 return;
557}
953f8681 558#endif
d12fd121 559
d0d66c44 560
a750e77c 561static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
d61e5808 562 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
0b8f18e3 563 struct cifs_fattr *fattr)
d0d66c44
SP
564{
565 int i;
566 int num_aces = 0;
567 int acl_size;
568 char *acl_base;
d0d66c44
SP
569 struct cifs_ace **ppace;
570
571 /* BB need to add parm so we can store the SID BB */
572
2b83457b
SF
573 if (!pdacl) {
574 /* no DACL in the security descriptor, set
575 all the permissions for user/group/other */
0b8f18e3 576 fattr->cf_mode |= S_IRWXUGO;
2b83457b
SF
577 return;
578 }
579
d0d66c44 580 /* validate that we do not go past end of acl */
af6f4612 581 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
b6b38f70 582 cERROR(1, "ACL too small to parse DACL");
d0d66c44
SP
583 return;
584 }
585
b6b38f70 586 cFYI(DBG2, "DACL revision %d size %d num aces %d",
af6f4612 587 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
b6b38f70 588 le32_to_cpu(pdacl->num_aces));
d0d66c44 589
7505e052
SF
590 /* reset rwx permissions for user/group/other.
591 Also, if num_aces is 0 i.e. DACL has no ACEs,
592 user/group/other have no permissions */
0b8f18e3 593 fattr->cf_mode &= ~(S_IRWXUGO);
7505e052 594
d0d66c44
SP
595 acl_base = (char *)pdacl;
596 acl_size = sizeof(struct cifs_acl);
597
adbc0358 598 num_aces = le32_to_cpu(pdacl->num_aces);
a5ff3769 599 if (num_aces > 0) {
15b03959
SF
600 umode_t user_mask = S_IRWXU;
601 umode_t group_mask = S_IRWXG;
2fbc2f17 602 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
15b03959 603
7250170c
DC
604 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
605 return;
d0d66c44
SP
606 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
607 GFP_KERNEL);
8132b65b
SF
608 if (!ppace) {
609 cERROR(1, "DACL memory allocation error");
610 return;
611 }
d0d66c44 612
d0d66c44 613 for (i = 0; i < num_aces; ++i) {
44093ca2 614 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
953f8681
SF
615#ifdef CONFIG_CIFS_DEBUG2
616 dump_ace(ppace[i], end_of_acl);
617#endif
9409ae58 618 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
e01b6400 619 access_flags_to_mode(ppace[i]->access_req,
15b03959 620 ppace[i]->type,
0b8f18e3 621 &fattr->cf_mode,
15b03959 622 &user_mask);
9409ae58 623 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
e01b6400 624 access_flags_to_mode(ppace[i]->access_req,
15b03959 625 ppace[i]->type,
0b8f18e3 626 &fattr->cf_mode,
15b03959 627 &group_mask);
9409ae58 628 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
e01b6400 629 access_flags_to_mode(ppace[i]->access_req,
15b03959 630 ppace[i]->type,
0b8f18e3 631 &fattr->cf_mode,
15b03959 632 &other_mask);
9409ae58 633 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
2fbc2f17
SP
634 access_flags_to_mode(ppace[i]->access_req,
635 ppace[i]->type,
636 &fattr->cf_mode,
637 &other_mask);
638
e01b6400 639
44093ca2 640/* memcpy((void *)(&(cifscred->aces[i])),
d12fd121
SF
641 (void *)ppace[i],
642 sizeof(struct cifs_ace)); */
d0d66c44 643
44093ca2
SF
644 acl_base = (char *)ppace[i];
645 acl_size = le16_to_cpu(ppace[i]->size);
d0d66c44
SP
646 }
647
648 kfree(ppace);
d0d66c44
SP
649 }
650
651 return;
652}
653
bcb02034 654
97837582
SF
655static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
656 struct cifs_sid *pgrpsid, __u64 nmode)
657{
2b210adc 658 u16 size = 0;
97837582
SF
659 struct cifs_acl *pnndacl;
660
661 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
662
663 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
664 pownersid, nmode, S_IRWXU);
665 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
666 pgrpsid, nmode, S_IRWXG);
667 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
668 &sid_everyone, nmode, S_IRWXO);
669
670 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
d9f382ef 671 pndacl->num_aces = cpu_to_le32(3);
97837582 672
ef571cad 673 return 0;
97837582
SF
674}
675
676
bcb02034
SF
677static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
678{
679 /* BB need to add parm so we can store the SID BB */
680
b9c7a2bb
SF
681 /* validate that we do not go past end of ACL - sid must be at least 8
682 bytes long (assuming no sub-auths - e.g. the null SID */
683 if (end_of_acl < (char *)psid + 8) {
b6b38f70 684 cERROR(1, "ACL too small to parse SID %p", psid);
bcb02034
SF
685 return -EINVAL;
686 }
d0d66c44 687
bcb02034 688#ifdef CONFIG_CIFS_DEBUG2
fc03d8a5 689 if (psid->num_subauth) {
8f18c131 690 int i;
b6b38f70
JP
691 cFYI(1, "SID revision %d num_auth %d",
692 psid->revision, psid->num_subauth);
bcb02034 693
af6f4612 694 for (i = 0; i < psid->num_subauth; i++) {
b6b38f70
JP
695 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
696 le32_to_cpu(psid->sub_auth[i]));
d0d66c44
SP
697 }
698
d12fd121 699 /* BB add length check to make sure that we do not have huge
d0d66c44 700 num auths and therefore go off the end */
b6b38f70
JP
701 cFYI(1, "RID 0x%x",
702 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
d0d66c44 703 }
fc03d8a5 704#endif
d0d66c44 705
bcb02034
SF
706 return 0;
707}
708
d0d66c44 709
bcb02034 710/* Convert CIFS ACL to POSIX form */
9409ae58
SP
711static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
712 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
bcb02034 713{
9409ae58 714 int rc = 0;
bcb02034
SF
715 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
716 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
bcb02034 717 char *end_of_acl = ((char *)pntsd) + acl_len;
7505e052 718 __u32 dacloffset;
bcb02034 719
0b8f18e3 720 if (pntsd == NULL)
b9c7a2bb
SF
721 return -EIO;
722
bcb02034 723 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 724 le32_to_cpu(pntsd->osidoffset));
bcb02034 725 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
af6f4612 726 le32_to_cpu(pntsd->gsidoffset));
7505e052 727 dacloffset = le32_to_cpu(pntsd->dacloffset);
63d2583f 728 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
b6b38f70 729 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
bcb02034 730 "sacloffset 0x%x dacloffset 0x%x",
af6f4612
SF
731 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
732 le32_to_cpu(pntsd->gsidoffset),
b6b38f70 733 le32_to_cpu(pntsd->sacloffset), dacloffset);
b9c7a2bb 734/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
bcb02034 735 rc = parse_sid(owner_sid_ptr, end_of_acl);
9409ae58
SP
736 if (rc) {
737 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
738 return rc;
739 }
740 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
741 if (rc) {
742 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
bcb02034 743 return rc;
9409ae58 744 }
bcb02034
SF
745
746 rc = parse_sid(group_sid_ptr, end_of_acl);
9409ae58
SP
747 if (rc) {
748 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
bcb02034 749 return rc;
9409ae58
SP
750 }
751 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
752 if (rc) {
753 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
754 return rc;
755 }
bcb02034 756
7505e052
SF
757 if (dacloffset)
758 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
0b8f18e3 759 group_sid_ptr, fattr);
7505e052 760 else
b6b38f70 761 cFYI(1, "no ACL"); /* BB grant all or default perms? */
d0d66c44 762
9409ae58 763 return rc;
bcb02034 764}
b9c7a2bb 765
97837582
SF
766/* Convert permission bits from mode to equivalent CIFS ACL */
767static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
a5ff3769 768 __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
97837582
SF
769{
770 int rc = 0;
771 __u32 dacloffset;
772 __u32 ndacloffset;
773 __u32 sidsoffset;
774 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
a5ff3769 775 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
97837582
SF
776 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
777 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
778
a5ff3769
SP
779 if (nmode != NO_CHANGE_64) { /* chmod */
780 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 781 le32_to_cpu(pntsd->osidoffset));
a5ff3769 782 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
97837582 783 le32_to_cpu(pntsd->gsidoffset));
a5ff3769
SP
784 dacloffset = le32_to_cpu(pntsd->dacloffset);
785 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
786 ndacloffset = sizeof(struct cifs_ntsd);
787 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
788 ndacl_ptr->revision = dacl_ptr->revision;
789 ndacl_ptr->size = 0;
790 ndacl_ptr->num_aces = 0;
791
792 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
793 nmode);
794 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
795 /* copy sec desc control portion & owner and group sids */
796 copy_sec_desc(pntsd, pnntsd, sidsoffset);
797 *aclflag = CIFS_ACL_DACL;
798 } else {
799 memcpy(pnntsd, pntsd, secdesclen);
800 if (uid != NO_CHANGE_32) { /* chown */
801 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
802 le32_to_cpu(pnntsd->osidoffset));
803 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
804 GFP_KERNEL);
805 if (!nowner_sid_ptr)
806 return -ENOMEM;
807 rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
808 if (rc) {
809 cFYI(1, "%s: Mapping error %d for owner id %d",
810 __func__, rc, uid);
811 kfree(nowner_sid_ptr);
812 return rc;
813 }
36960e44 814 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
a5ff3769
SP
815 kfree(nowner_sid_ptr);
816 *aclflag = CIFS_ACL_OWNER;
817 }
818 if (gid != NO_CHANGE_32) { /* chgrp */
819 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
820 le32_to_cpu(pnntsd->gsidoffset));
821 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
822 GFP_KERNEL);
823 if (!ngroup_sid_ptr)
824 return -ENOMEM;
825 rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
826 if (rc) {
827 cFYI(1, "%s: Mapping error %d for group id %d",
828 __func__, rc, gid);
829 kfree(ngroup_sid_ptr);
830 return rc;
831 }
36960e44 832 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
a5ff3769
SP
833 kfree(ngroup_sid_ptr);
834 *aclflag = CIFS_ACL_GROUP;
835 }
836 }
97837582 837
ef571cad 838 return rc;
97837582
SF
839}
840
1bf4072d
CH
841static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
842 __u16 fid, u32 *pacllen)
b9c7a2bb 843{
b9c7a2bb 844 struct cifs_ntsd *pntsd = NULL;
6d5786a3
PS
845 unsigned int xid;
846 int rc;
7ffec372
JL
847 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
848
849 if (IS_ERR(tlink))
987b21d7 850 return ERR_CAST(tlink);
b9c7a2bb 851
6d5786a3 852 xid = get_xid();
7ffec372 853 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
6d5786a3 854 free_xid(xid);
b9c7a2bb 855
7ffec372 856 cifs_put_tlink(tlink);
b9c7a2bb 857
987b21d7
SP
858 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
859 if (rc)
860 return ERR_PTR(rc);
1bf4072d
CH
861 return pntsd;
862}
8b1327f6 863
1bf4072d
CH
864static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
865 const char *path, u32 *pacllen)
866{
867 struct cifs_ntsd *pntsd = NULL;
868 int oplock = 0;
6d5786a3
PS
869 unsigned int xid;
870 int rc, create_options = 0;
1bf4072d 871 __u16 fid;
96daf2b0 872 struct cifs_tcon *tcon;
7ffec372
JL
873 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
874
875 if (IS_ERR(tlink))
987b21d7 876 return ERR_CAST(tlink);
b9c7a2bb 877
7ffec372 878 tcon = tlink_tcon(tlink);
6d5786a3 879 xid = get_xid();
1bf4072d 880
3d3ea8e6
SP
881 if (backup_cred(cifs_sb))
882 create_options |= CREATE_OPEN_BACKUP_INTENT;
883
884 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
885 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
886 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
987b21d7
SP
887 if (!rc) {
888 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
889 CIFSSMBClose(xid, tcon, fid);
b9c7a2bb
SF
890 }
891
7ffec372 892 cifs_put_tlink(tlink);
6d5786a3 893 free_xid(xid);
987b21d7
SP
894
895 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
896 if (rc)
897 return ERR_PTR(rc);
7505e052
SF
898 return pntsd;
899}
900
1bf4072d 901/* Retrieve an ACL from the server */
fbeba8bb 902struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1bf4072d
CH
903 struct inode *inode, const char *path,
904 u32 *pacllen)
905{
906 struct cifs_ntsd *pntsd = NULL;
907 struct cifsFileInfo *open_file = NULL;
908
909 if (inode)
6508d904 910 open_file = find_readable_file(CIFS_I(inode), true);
1bf4072d
CH
911 if (!open_file)
912 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
913
4b4de76e 914 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
6ab409b5 915 cifsFileInfo_put(open_file);
1bf4072d
CH
916 return pntsd;
917}
918
a5ff3769
SP
919 /* Set an ACL on the server */
920int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
921 struct inode *inode, const char *path, int aclflag)
b96d31a6
CH
922{
923 int oplock = 0;
6d5786a3
PS
924 unsigned int xid;
925 int rc, access_flags, create_options = 0;
b96d31a6 926 __u16 fid;
96daf2b0 927 struct cifs_tcon *tcon;
a5ff3769 928 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
7ffec372 929 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
97837582 930
7ffec372
JL
931 if (IS_ERR(tlink))
932 return PTR_ERR(tlink);
933
934 tcon = tlink_tcon(tlink);
6d5786a3 935 xid = get_xid();
97837582 936
3d3ea8e6
SP
937 if (backup_cred(cifs_sb))
938 create_options |= CREATE_OPEN_BACKUP_INTENT;
939
a5ff3769
SP
940 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
941 access_flags = WRITE_OWNER;
942 else
943 access_flags = WRITE_DAC;
944
945 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
946 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
947 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
b96d31a6 948 if (rc) {
b6b38f70 949 cERROR(1, "Unable to open file to set ACL");
b96d31a6 950 goto out;
97837582
SF
951 }
952
a5ff3769 953 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
b6b38f70 954 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
97837582 955
7ffec372
JL
956 CIFSSMBClose(xid, tcon, fid);
957out:
6d5786a3 958 free_xid(xid);
7ffec372 959 cifs_put_tlink(tlink);
b96d31a6
CH
960 return rc;
961}
97837582 962
7505e052 963/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
987b21d7 964int
0b8f18e3
JL
965cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
966 struct inode *inode, const char *path, const __u16 *pfid)
7505e052
SF
967{
968 struct cifs_ntsd *pntsd = NULL;
969 u32 acllen = 0;
970 int rc = 0;
971
b6b38f70 972 cFYI(DBG2, "converting ACL to mode for %s", path);
1bf4072d
CH
973
974 if (pfid)
975 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
976 else
977 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
7505e052
SF
978
979 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
987b21d7
SP
980 if (IS_ERR(pntsd)) {
981 rc = PTR_ERR(pntsd);
982 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
983 } else {
9409ae58 984 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
987b21d7
SP
985 kfree(pntsd);
986 if (rc)
987 cERROR(1, "parse sec desc failed rc = %d", rc);
988 }
7505e052 989
987b21d7 990 return rc;
b9c7a2bb 991}
953f8681 992
7505e052 993/* Convert mode bits to an ACL so we can update the ACL on the server */
a5ff3769
SP
994int
995id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
996 uid_t uid, gid_t gid)
953f8681
SF
997{
998 int rc = 0;
a5ff3769 999 int aclflag = CIFS_ACL_DACL; /* default flag to set */
cce246ee 1000 __u32 secdesclen = 0;
97837582
SF
1001 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1002 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
953f8681 1003
b6b38f70 1004 cFYI(DBG2, "set ACL from mode for %s", path);
953f8681
SF
1005
1006 /* Get the security descriptor */
1bf4072d 1007 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
987b21d7
SP
1008 if (IS_ERR(pntsd)) {
1009 rc = PTR_ERR(pntsd);
1010 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
c78cd838
JL
1011 goto out;
1012 }
7505e052 1013
c78cd838
JL
1014 /*
1015 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1016 * as chmod disables ACEs and set the security descriptor. Allocate
1017 * memory for the smb header, set security descriptor request security
1018 * descriptor parameters, and secuirty descriptor itself
1019 */
7ee0b4c6 1020 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
c78cd838
JL
1021 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1022 if (!pnntsd) {
1023 cERROR(1, "Unable to allocate security descriptor");
1024 kfree(pntsd);
1025 return -ENOMEM;
1026 }
97837582 1027
c78cd838
JL
1028 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1029 &aclflag);
97837582 1030
c78cd838 1031 cFYI(DBG2, "build_sec_desc rc: %d", rc);
97837582 1032
c78cd838
JL
1033 if (!rc) {
1034 /* Set the security descriptor */
1035 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1036 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
97837582
SF
1037 }
1038
c78cd838
JL
1039 kfree(pnntsd);
1040 kfree(pntsd);
1041out:
ef571cad 1042 return rc;
953f8681 1043}