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 <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/keyctl.h>
28 #include <linux/key-type.h>
29 #include <keys/user-type.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsacl.h"
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
35
36 /* security id for everyone/world system group */
37 static const struct cifs_sid sid_everyone = {
38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39 /* security id for Authenticated Users system group */
40 static const struct cifs_sid sid_authusers = {
41 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
42
43 /* S-1-22-1 Unmapped Unix users */
44 static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
45 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
46
47 /* S-1-22-2 Unmapped Unix groups */
48 static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
49 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
50
51 /*
52 * See https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
53 */
54
55 /* S-1-5-88 MS NFS and Apple style UID/GID/mode */
56
57 /* S-1-5-88-1 Unix uid */
58 static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
59 {cpu_to_le32(88),
60 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
61
62 /* S-1-5-88-2 Unix gid */
63 static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
64 {cpu_to_le32(88),
65 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
66
67 /* S-1-5-88-3 Unix mode */
68 static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
69 {cpu_to_le32(88),
70 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
71
72 static const struct cred *root_cred;
73
74 static int
cifs_idmap_key_instantiate(struct key * key,struct key_preparsed_payload * prep)75 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
76 {
77 char *payload;
78
79 /*
80 * If the payload is less than or equal to the size of a pointer, then
81 * an allocation here is wasteful. Just copy the data directly to the
82 * payload.value union member instead.
83 *
84 * With this however, you must check the datalen before trying to
85 * dereference payload.data!
86 */
87 if (prep->datalen <= sizeof(key->payload)) {
88 key->payload.data[0] = NULL;
89 memcpy(&key->payload, prep->data, prep->datalen);
90 } else {
91 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
92 if (!payload)
93 return -ENOMEM;
94 key->payload.data[0] = payload;
95 }
96
97 key->datalen = prep->datalen;
98 return 0;
99 }
100
101 static inline void
cifs_idmap_key_destroy(struct key * key)102 cifs_idmap_key_destroy(struct key *key)
103 {
104 if (key->datalen > sizeof(key->payload))
105 kfree(key->payload.data[0]);
106 }
107
108 static struct key_type cifs_idmap_key_type = {
109 .name = "cifs.idmap",
110 .instantiate = cifs_idmap_key_instantiate,
111 .destroy = cifs_idmap_key_destroy,
112 .describe = user_describe,
113 };
114
115 static char *
sid_to_key_str(struct cifs_sid * sidptr,unsigned int type)116 sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
117 {
118 int i, len;
119 unsigned int saval;
120 char *sidstr, *strptr;
121 unsigned long long id_auth_val;
122
123 /* 3 bytes for prefix */
124 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
125 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
126 GFP_KERNEL);
127 if (!sidstr)
128 return sidstr;
129
130 strptr = sidstr;
131 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
132 sidptr->revision);
133 strptr += len;
134
135 /* The authority field is a single 48-bit number */
136 id_auth_val = (unsigned long long)sidptr->authority[5];
137 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
138 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
139 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
140 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
141 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
142
143 /*
144 * MS-DTYP states that if the authority is >= 2^32, then it should be
145 * expressed as a hex value.
146 */
147 if (id_auth_val <= UINT_MAX)
148 len = sprintf(strptr, "-%llu", id_auth_val);
149 else
150 len = sprintf(strptr, "-0x%llx", id_auth_val);
151
152 strptr += len;
153
154 for (i = 0; i < sidptr->num_subauth; ++i) {
155 saval = le32_to_cpu(sidptr->sub_auth[i]);
156 len = sprintf(strptr, "-%u", saval);
157 strptr += len;
158 }
159
160 return sidstr;
161 }
162
163 /*
164 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
165 * the same returns zero, if they do not match returns non-zero.
166 */
167 static int
compare_sids(const struct cifs_sid * ctsid,const struct cifs_sid * cwsid)168 compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
169 {
170 int i;
171 int num_subauth, num_sat, num_saw;
172
173 if ((!ctsid) || (!cwsid))
174 return 1;
175
176 /* compare the revision */
177 if (ctsid->revision != cwsid->revision) {
178 if (ctsid->revision > cwsid->revision)
179 return 1;
180 else
181 return -1;
182 }
183
184 /* compare all of the six auth values */
185 for (i = 0; i < NUM_AUTHS; ++i) {
186 if (ctsid->authority[i] != cwsid->authority[i]) {
187 if (ctsid->authority[i] > cwsid->authority[i])
188 return 1;
189 else
190 return -1;
191 }
192 }
193
194 /* compare all of the subauth values if any */
195 num_sat = ctsid->num_subauth;
196 num_saw = cwsid->num_subauth;
197 num_subauth = num_sat < num_saw ? num_sat : num_saw;
198 if (num_subauth) {
199 for (i = 0; i < num_subauth; ++i) {
200 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
201 if (le32_to_cpu(ctsid->sub_auth[i]) >
202 le32_to_cpu(cwsid->sub_auth[i]))
203 return 1;
204 else
205 return -1;
206 }
207 }
208 }
209
210 return 0; /* sids compare/match */
211 }
212
213 static bool
is_well_known_sid(const struct cifs_sid * psid,uint32_t * puid,bool is_group)214 is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
215 {
216 int i;
217 int num_subauth;
218 const struct cifs_sid *pwell_known_sid;
219
220 if (!psid || (puid == NULL))
221 return false;
222
223 num_subauth = psid->num_subauth;
224
225 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
226 if (num_subauth == 2) {
227 if (is_group)
228 pwell_known_sid = &sid_unix_groups;
229 else
230 pwell_known_sid = &sid_unix_users;
231 } else if (num_subauth == 3) {
232 if (is_group)
233 pwell_known_sid = &sid_unix_NFS_groups;
234 else
235 pwell_known_sid = &sid_unix_NFS_users;
236 } else
237 return false;
238
239 /* compare the revision */
240 if (psid->revision != pwell_known_sid->revision)
241 return false;
242
243 /* compare all of the six auth values */
244 for (i = 0; i < NUM_AUTHS; ++i) {
245 if (psid->authority[i] != pwell_known_sid->authority[i]) {
246 cifs_dbg(FYI, "auth %d did not match\n", i);
247 return false;
248 }
249 }
250
251 if (num_subauth == 2) {
252 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
253 return false;
254
255 *puid = le32_to_cpu(psid->sub_auth[1]);
256 } else /* 3 subauths, ie Windows/Mac style */ {
257 *puid = le32_to_cpu(psid->sub_auth[0]);
258 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
259 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
260 return false;
261
262 *puid = le32_to_cpu(psid->sub_auth[2]);
263 }
264
265 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
266 return true; /* well known sid found, uid returned */
267 }
268
269 static void
cifs_copy_sid(struct cifs_sid * dst,const struct cifs_sid * src)270 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
271 {
272 int i;
273
274 dst->revision = src->revision;
275 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
276 for (i = 0; i < NUM_AUTHS; ++i)
277 dst->authority[i] = src->authority[i];
278 for (i = 0; i < dst->num_subauth; ++i)
279 dst->sub_auth[i] = src->sub_auth[i];
280 }
281
282 static int
id_to_sid(unsigned int cid,uint sidtype,struct cifs_sid * ssid)283 id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
284 {
285 int rc;
286 struct key *sidkey;
287 struct cifs_sid *ksid;
288 unsigned int ksid_size;
289 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
290 const struct cred *saved_cred;
291
292 rc = snprintf(desc, sizeof(desc), "%ci:%u",
293 sidtype == SIDOWNER ? 'o' : 'g', cid);
294 if (rc >= sizeof(desc))
295 return -EINVAL;
296
297 rc = 0;
298 saved_cred = override_creds(root_cred);
299 sidkey = request_key(&cifs_idmap_key_type, desc, "");
300 if (IS_ERR(sidkey)) {
301 rc = -EINVAL;
302 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
303 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
304 goto out_revert_creds;
305 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
306 rc = -EIO;
307 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
308 __func__, sidkey->datalen);
309 goto invalidate_key;
310 }
311
312 /*
313 * A sid is usually too large to be embedded in payload.value, but if
314 * there are no subauthorities and the host has 8-byte pointers, then
315 * it could be.
316 */
317 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
318 (struct cifs_sid *)&sidkey->payload :
319 (struct cifs_sid *)sidkey->payload.data[0];
320
321 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
322 if (ksid_size > sidkey->datalen) {
323 rc = -EIO;
324 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
325 __func__, sidkey->datalen, ksid_size);
326 goto invalidate_key;
327 }
328
329 cifs_copy_sid(ssid, ksid);
330 out_key_put:
331 key_put(sidkey);
332 out_revert_creds:
333 revert_creds(saved_cred);
334 return rc;
335
336 invalidate_key:
337 key_invalidate(sidkey);
338 goto out_key_put;
339 }
340
341 int
sid_to_id(struct cifs_sb_info * cifs_sb,struct cifs_sid * psid,struct cifs_fattr * fattr,uint sidtype)342 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
343 struct cifs_fattr *fattr, uint sidtype)
344 {
345 int rc = 0;
346 struct key *sidkey;
347 char *sidstr;
348 const struct cred *saved_cred;
349 kuid_t fuid = cifs_sb->mnt_uid;
350 kgid_t fgid = cifs_sb->mnt_gid;
351
352 /*
353 * If we have too many subauthorities, then something is really wrong.
354 * Just return an error.
355 */
356 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
357 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
358 __func__, psid->num_subauth);
359 return -EIO;
360 }
361
362 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
363 (cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
364 uint32_t unix_id;
365 bool is_group;
366
367 if (sidtype != SIDOWNER)
368 is_group = true;
369 else
370 is_group = false;
371
372 if (is_well_known_sid(psid, &unix_id, is_group) == false)
373 goto try_upcall_to_get_id;
374
375 if (is_group) {
376 kgid_t gid;
377 gid_t id;
378
379 id = (gid_t)unix_id;
380 gid = make_kgid(&init_user_ns, id);
381 if (gid_valid(gid)) {
382 fgid = gid;
383 goto got_valid_id;
384 }
385 } else {
386 kuid_t uid;
387 uid_t id;
388
389 id = (uid_t)unix_id;
390 uid = make_kuid(&init_user_ns, id);
391 if (uid_valid(uid)) {
392 fuid = uid;
393 goto got_valid_id;
394 }
395 }
396 /* If unable to find uid/gid easily from SID try via upcall */
397 }
398
399 try_upcall_to_get_id:
400 sidstr = sid_to_key_str(psid, sidtype);
401 if (!sidstr)
402 return -ENOMEM;
403
404 saved_cred = override_creds(root_cred);
405 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
406 if (IS_ERR(sidkey)) {
407 rc = -EINVAL;
408 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
409 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
410 goto out_revert_creds;
411 }
412
413 /*
414 * FIXME: Here we assume that uid_t and gid_t are same size. It's
415 * probably a safe assumption but might be better to check based on
416 * sidtype.
417 */
418 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
419 if (sidkey->datalen != sizeof(uid_t)) {
420 rc = -EIO;
421 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
422 __func__, sidkey->datalen);
423 key_invalidate(sidkey);
424 goto out_key_put;
425 }
426
427 if (sidtype == SIDOWNER) {
428 kuid_t uid;
429 uid_t id;
430 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
431 uid = make_kuid(&init_user_ns, id);
432 if (uid_valid(uid))
433 fuid = uid;
434 } else {
435 kgid_t gid;
436 gid_t id;
437 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
438 gid = make_kgid(&init_user_ns, id);
439 if (gid_valid(gid))
440 fgid = gid;
441 }
442
443 out_key_put:
444 key_put(sidkey);
445 out_revert_creds:
446 revert_creds(saved_cred);
447 kfree(sidstr);
448
449 /*
450 * Note that we return 0 here unconditionally. If the mapping
451 * fails then we just fall back to using the mnt_uid/mnt_gid.
452 */
453 got_valid_id:
454 rc = 0;
455 if (sidtype == SIDOWNER)
456 fattr->cf_uid = fuid;
457 else
458 fattr->cf_gid = fgid;
459 return rc;
460 }
461
462 int
init_cifs_idmap(void)463 init_cifs_idmap(void)
464 {
465 struct cred *cred;
466 struct key *keyring;
467 int ret;
468
469 cifs_dbg(FYI, "Registering the %s key type\n",
470 cifs_idmap_key_type.name);
471
472 /* create an override credential set with a special thread keyring in
473 * which requests are cached
474 *
475 * this is used to prevent malicious redirections from being installed
476 * with add_key().
477 */
478 cred = prepare_kernel_cred(NULL);
479 if (!cred)
480 return -ENOMEM;
481
482 keyring = keyring_alloc(".cifs_idmap",
483 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
484 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
485 KEY_USR_VIEW | KEY_USR_READ,
486 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
487 if (IS_ERR(keyring)) {
488 ret = PTR_ERR(keyring);
489 goto failed_put_cred;
490 }
491
492 ret = register_key_type(&cifs_idmap_key_type);
493 if (ret < 0)
494 goto failed_put_key;
495
496 /* instruct request_key() to use this special keyring as a cache for
497 * the results it looks up */
498 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
499 cred->thread_keyring = keyring;
500 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
501 root_cred = cred;
502
503 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
504 return 0;
505
506 failed_put_key:
507 key_put(keyring);
508 failed_put_cred:
509 put_cred(cred);
510 return ret;
511 }
512
513 void
exit_cifs_idmap(void)514 exit_cifs_idmap(void)
515 {
516 key_revoke(root_cred->thread_keyring);
517 unregister_key_type(&cifs_idmap_key_type);
518 put_cred(root_cred);
519 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
520 }
521
522 /* 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)523 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
524 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
525 {
526 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
527 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
528
529 /* copy security descriptor control portion */
530 pnntsd->revision = pntsd->revision;
531 pnntsd->type = pntsd->type;
532 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
533 pnntsd->sacloffset = 0;
534 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
535 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
536
537 /* copy owner sid */
538 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
539 le32_to_cpu(pntsd->osidoffset));
540 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
541 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
542
543 /* copy group sid */
544 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
545 le32_to_cpu(pntsd->gsidoffset));
546 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
547 sizeof(struct cifs_sid));
548 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
549
550 return;
551 }
552
553
554 /*
555 change posix mode to reflect permissions
556 pmode is the existing mode (we only want to overwrite part of this
557 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
558 */
access_flags_to_mode(__le32 ace_flags,int type,umode_t * pmode,umode_t * pbits_to_set)559 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
560 umode_t *pbits_to_set)
561 {
562 __u32 flags = le32_to_cpu(ace_flags);
563 /* the order of ACEs is important. The canonical order is to begin with
564 DENY entries followed by ALLOW, otherwise an allow entry could be
565 encountered first, making the subsequent deny entry like "dead code"
566 which would be superflous since Windows stops when a match is made
567 for the operation you are trying to perform for your user */
568
569 /* For deny ACEs we change the mask so that subsequent allow access
570 control entries do not turn on the bits we are denying */
571 if (type == ACCESS_DENIED) {
572 if (flags & GENERIC_ALL)
573 *pbits_to_set &= ~S_IRWXUGO;
574
575 if ((flags & GENERIC_WRITE) ||
576 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
577 *pbits_to_set &= ~S_IWUGO;
578 if ((flags & GENERIC_READ) ||
579 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
580 *pbits_to_set &= ~S_IRUGO;
581 if ((flags & GENERIC_EXECUTE) ||
582 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
583 *pbits_to_set &= ~S_IXUGO;
584 return;
585 } else if (type != ACCESS_ALLOWED) {
586 cifs_dbg(VFS, "unknown access control type %d\n", type);
587 return;
588 }
589 /* else ACCESS_ALLOWED type */
590
591 if (flags & GENERIC_ALL) {
592 *pmode |= (S_IRWXUGO & (*pbits_to_set));
593 cifs_dbg(NOISY, "all perms\n");
594 return;
595 }
596 if ((flags & GENERIC_WRITE) ||
597 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
598 *pmode |= (S_IWUGO & (*pbits_to_set));
599 if ((flags & GENERIC_READ) ||
600 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
601 *pmode |= (S_IRUGO & (*pbits_to_set));
602 if ((flags & GENERIC_EXECUTE) ||
603 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
604 *pmode |= (S_IXUGO & (*pbits_to_set));
605
606 cifs_dbg(NOISY, "access flags 0x%x mode now %04o\n", flags, *pmode);
607 return;
608 }
609
610 /*
611 Generate access flags to reflect permissions mode is the existing mode.
612 This function is called for every ACE in the DACL whose SID matches
613 with either owner or group or everyone.
614 */
615
mode_to_access_flags(umode_t mode,umode_t bits_to_use,__u32 * pace_flags)616 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
617 __u32 *pace_flags)
618 {
619 /* reset access mask */
620 *pace_flags = 0x0;
621
622 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
623 mode &= bits_to_use;
624
625 /* check for R/W/X UGO since we do not know whose flags
626 is this but we have cleared all the bits sans RWX for
627 either user or group or other as per bits_to_use */
628 if (mode & S_IRUGO)
629 *pace_flags |= SET_FILE_READ_RIGHTS;
630 if (mode & S_IWUGO)
631 *pace_flags |= SET_FILE_WRITE_RIGHTS;
632 if (mode & S_IXUGO)
633 *pace_flags |= SET_FILE_EXEC_RIGHTS;
634
635 cifs_dbg(NOISY, "mode: %04o, access flags now 0x%x\n",
636 mode, *pace_flags);
637 return;
638 }
639
fill_ace_for_sid(struct cifs_ace * pntace,const struct cifs_sid * psid,__u64 nmode,umode_t bits)640 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
641 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
642 {
643 int i;
644 __u16 size = 0;
645 __u32 access_req = 0;
646
647 pntace->type = ACCESS_ALLOWED;
648 pntace->flags = 0x0;
649 mode_to_access_flags(nmode, bits, &access_req);
650 if (!access_req)
651 access_req = SET_MINIMUM_RIGHTS;
652 pntace->access_req = cpu_to_le32(access_req);
653
654 pntace->sid.revision = psid->revision;
655 pntace->sid.num_subauth = psid->num_subauth;
656 for (i = 0; i < NUM_AUTHS; i++)
657 pntace->sid.authority[i] = psid->authority[i];
658 for (i = 0; i < psid->num_subauth; i++)
659 pntace->sid.sub_auth[i] = psid->sub_auth[i];
660
661 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
662 pntace->size = cpu_to_le16(size);
663
664 return size;
665 }
666
667
668 #ifdef CONFIG_CIFS_DEBUG2
dump_ace(struct cifs_ace * pace,char * end_of_acl)669 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
670 {
671 int num_subauth;
672
673 /* validate that we do not go past end of acl */
674
675 if (le16_to_cpu(pace->size) < 16) {
676 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
677 return;
678 }
679
680 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
681 cifs_dbg(VFS, "ACL too small to parse ACE\n");
682 return;
683 }
684
685 num_subauth = pace->sid.num_subauth;
686 if (num_subauth) {
687 int i;
688 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
689 pace->sid.revision, pace->sid.num_subauth, pace->type,
690 pace->flags, le16_to_cpu(pace->size));
691 for (i = 0; i < num_subauth; ++i) {
692 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
693 i, le32_to_cpu(pace->sid.sub_auth[i]));
694 }
695
696 /* BB add length check to make sure that we do not have huge
697 num auths and therefore go off the end */
698 }
699
700 return;
701 }
702 #endif
703
parse_dacl(struct cifs_acl * pdacl,char * end_of_acl,struct cifs_sid * pownersid,struct cifs_sid * pgrpsid,struct cifs_fattr * fattr,bool mode_from_special_sid)704 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
705 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
706 struct cifs_fattr *fattr, bool mode_from_special_sid)
707 {
708 int i;
709 int num_aces = 0;
710 int acl_size;
711 char *acl_base;
712 struct cifs_ace **ppace;
713
714 /* BB need to add parm so we can store the SID BB */
715
716 if (!pdacl) {
717 /* no DACL in the security descriptor, set
718 all the permissions for user/group/other */
719 fattr->cf_mode |= S_IRWXUGO;
720 return;
721 }
722
723 /* validate that we do not go past end of acl */
724 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
725 cifs_dbg(VFS, "ACL too small to parse DACL\n");
726 return;
727 }
728
729 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
730 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
731 le32_to_cpu(pdacl->num_aces));
732
733 /* reset rwx permissions for user/group/other.
734 Also, if num_aces is 0 i.e. DACL has no ACEs,
735 user/group/other have no permissions */
736 fattr->cf_mode &= ~(S_IRWXUGO);
737
738 acl_base = (char *)pdacl;
739 acl_size = sizeof(struct cifs_acl);
740
741 num_aces = le32_to_cpu(pdacl->num_aces);
742 if (num_aces > 0) {
743 umode_t user_mask = S_IRWXU;
744 umode_t group_mask = S_IRWXG;
745 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
746
747 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
748 return;
749 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
750 GFP_KERNEL);
751 if (!ppace)
752 return;
753
754 for (i = 0; i < num_aces; ++i) {
755 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
756 #ifdef CONFIG_CIFS_DEBUG2
757 dump_ace(ppace[i], end_of_acl);
758 #endif
759 if (mode_from_special_sid &&
760 (compare_sids(&(ppace[i]->sid),
761 &sid_unix_NFS_mode) == 0)) {
762 /*
763 * Full permissions are:
764 * 07777 = S_ISUID | S_ISGID | S_ISVTX |
765 * S_IRWXU | S_IRWXG | S_IRWXO
766 */
767 fattr->cf_mode &= ~07777;
768 fattr->cf_mode |=
769 le32_to_cpu(ppace[i]->sid.sub_auth[2]);
770 break;
771 } else if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
772 access_flags_to_mode(ppace[i]->access_req,
773 ppace[i]->type,
774 &fattr->cf_mode,
775 &user_mask);
776 else if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
777 access_flags_to_mode(ppace[i]->access_req,
778 ppace[i]->type,
779 &fattr->cf_mode,
780 &group_mask);
781 else if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
782 access_flags_to_mode(ppace[i]->access_req,
783 ppace[i]->type,
784 &fattr->cf_mode,
785 &other_mask);
786 else if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
787 access_flags_to_mode(ppace[i]->access_req,
788 ppace[i]->type,
789 &fattr->cf_mode,
790 &other_mask);
791
792
793 /* memcpy((void *)(&(cifscred->aces[i])),
794 (void *)ppace[i],
795 sizeof(struct cifs_ace)); */
796
797 acl_base = (char *)ppace[i];
798 acl_size = le16_to_cpu(ppace[i]->size);
799 }
800
801 kfree(ppace);
802 }
803
804 return;
805 }
806
setup_authusers_ACE(struct cifs_ace * pntace)807 unsigned int setup_authusers_ACE(struct cifs_ace *pntace)
808 {
809 int i;
810 unsigned int ace_size = 20;
811
812 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
813 pntace->flags = 0x0;
814 pntace->access_req = cpu_to_le32(GENERIC_ALL);
815 pntace->sid.num_subauth = 1;
816 pntace->sid.revision = 1;
817 for (i = 0; i < NUM_AUTHS; i++)
818 pntace->sid.authority[i] = sid_authusers.authority[i];
819
820 pntace->sid.sub_auth[0] = sid_authusers.sub_auth[0];
821
822 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
823 pntace->size = cpu_to_le16(ace_size);
824 return ace_size;
825 }
826
827 /*
828 * Fill in the special SID based on the mode. See
829 * https://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
830 */
setup_special_mode_ACE(struct cifs_ace * pntace,__u64 nmode)831 unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
832 {
833 int i;
834 unsigned int ace_size = 28;
835
836 pntace->type = ACCESS_DENIED_ACE_TYPE;
837 pntace->flags = 0x0;
838 pntace->access_req = 0;
839 pntace->sid.num_subauth = 3;
840 pntace->sid.revision = 1;
841 for (i = 0; i < NUM_AUTHS; i++)
842 pntace->sid.authority[i] = sid_unix_NFS_mode.authority[i];
843
844 pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
845 pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
846 pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);
847
848 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
849 pntace->size = cpu_to_le16(ace_size);
850 return ace_size;
851 }
852
setup_special_user_owner_ACE(struct cifs_ace * pntace)853 unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
854 {
855 int i;
856 unsigned int ace_size = 28;
857
858 pntace->type = ACCESS_ALLOWED_ACE_TYPE;
859 pntace->flags = 0x0;
860 pntace->access_req = cpu_to_le32(GENERIC_ALL);
861 pntace->sid.num_subauth = 3;
862 pntace->sid.revision = 1;
863 for (i = 0; i < NUM_AUTHS; i++)
864 pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
865
866 pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
867 pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
868 pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
869
870 /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
871 pntace->size = cpu_to_le16(ace_size);
872 return ace_size;
873 }
874
set_chmod_dacl(struct cifs_acl * pndacl,struct cifs_sid * pownersid,struct cifs_sid * pgrpsid,__u64 nmode,bool modefromsid)875 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
876 struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
877 {
878 u16 size = 0;
879 u32 num_aces = 0;
880 struct cifs_acl *pnndacl;
881
882 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
883
884 if (modefromsid) {
885 struct cifs_ace *pntace =
886 (struct cifs_ace *)((char *)pnndacl + size);
887
888 size += setup_special_mode_ACE(pntace, nmode);
889 num_aces++;
890 }
891
892 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
893 pownersid, nmode, S_IRWXU);
894 num_aces++;
895 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
896 pgrpsid, nmode, S_IRWXG);
897 num_aces++;
898 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
899 &sid_everyone, nmode, S_IRWXO);
900 num_aces++;
901
902 pndacl->num_aces = cpu_to_le32(num_aces);
903 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
904
905 return 0;
906 }
907
908
parse_sid(struct cifs_sid * psid,char * end_of_acl)909 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
910 {
911 /* BB need to add parm so we can store the SID BB */
912
913 /* validate that we do not go past end of ACL - sid must be at least 8
914 bytes long (assuming no sub-auths - e.g. the null SID */
915 if (end_of_acl < (char *)psid + 8) {
916 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
917 return -EINVAL;
918 }
919
920 #ifdef CONFIG_CIFS_DEBUG2
921 if (psid->num_subauth) {
922 int i;
923 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
924 psid->revision, psid->num_subauth);
925
926 for (i = 0; i < psid->num_subauth; i++) {
927 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
928 i, le32_to_cpu(psid->sub_auth[i]));
929 }
930
931 /* BB add length check to make sure that we do not have huge
932 num auths and therefore go off the end */
933 cifs_dbg(FYI, "RID 0x%x\n",
934 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
935 }
936 #endif
937
938 return 0;
939 }
940
941
942 /* Convert CIFS ACL to POSIX form */
parse_sec_desc(struct cifs_sb_info * cifs_sb,struct cifs_ntsd * pntsd,int acl_len,struct cifs_fattr * fattr,bool get_mode_from_special_sid)943 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
944 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr,
945 bool get_mode_from_special_sid)
946 {
947 int rc = 0;
948 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
949 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
950 char *end_of_acl = ((char *)pntsd) + acl_len;
951 __u32 dacloffset;
952
953 if (pntsd == NULL)
954 return -EIO;
955
956 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
957 le32_to_cpu(pntsd->osidoffset));
958 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
959 le32_to_cpu(pntsd->gsidoffset));
960 dacloffset = le32_to_cpu(pntsd->dacloffset);
961 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
962 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
963 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
964 le32_to_cpu(pntsd->gsidoffset),
965 le32_to_cpu(pntsd->sacloffset), dacloffset);
966 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
967 rc = parse_sid(owner_sid_ptr, end_of_acl);
968 if (rc) {
969 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
970 return rc;
971 }
972 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
973 if (rc) {
974 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
975 __func__, rc);
976 return rc;
977 }
978
979 rc = parse_sid(group_sid_ptr, end_of_acl);
980 if (rc) {
981 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
982 __func__, rc);
983 return rc;
984 }
985 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
986 if (rc) {
987 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
988 __func__, rc);
989 return rc;
990 }
991
992 if (dacloffset)
993 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
994 group_sid_ptr, fattr, get_mode_from_special_sid);
995 else
996 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
997
998 return rc;
999 }
1000
1001 /* Convert permission bits from mode to equivalent CIFS ACL */
build_sec_desc(struct cifs_ntsd * pntsd,struct cifs_ntsd * pnntsd,__u32 secdesclen,__u64 nmode,kuid_t uid,kgid_t gid,bool mode_from_sid,bool id_from_sid,int * aclflag)1002 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
1003 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
1004 bool mode_from_sid, bool id_from_sid, int *aclflag)
1005 {
1006 int rc = 0;
1007 __u32 dacloffset;
1008 __u32 ndacloffset;
1009 __u32 sidsoffset;
1010 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1011 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
1012 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
1013 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1014
1015 if (nmode != NO_CHANGE_64) { /* chmod */
1016 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1017 le32_to_cpu(pntsd->osidoffset));
1018 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1019 le32_to_cpu(pntsd->gsidoffset));
1020 dacloffset = le32_to_cpu(pntsd->dacloffset);
1021 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1022 ndacloffset = sizeof(struct cifs_ntsd);
1023 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1024 ndacl_ptr->revision = dacl_ptr->revision;
1025 ndacl_ptr->size = 0;
1026 ndacl_ptr->num_aces = 0;
1027
1028 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
1029 nmode, mode_from_sid);
1030 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1031 /* copy sec desc control portion & owner and group sids */
1032 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1033 *aclflag = CIFS_ACL_DACL;
1034 } else {
1035 memcpy(pnntsd, pntsd, secdesclen);
1036 if (uid_valid(uid)) { /* chown */
1037 uid_t id;
1038 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1039 le32_to_cpu(pnntsd->osidoffset));
1040 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1041 GFP_KERNEL);
1042 if (!nowner_sid_ptr)
1043 return -ENOMEM;
1044 id = from_kuid(&init_user_ns, uid);
1045 if (id_from_sid) {
1046 struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
1047 /* Populate the user ownership fields S-1-5-88-1 */
1048 osid->Revision = 1;
1049 osid->NumAuth = 3;
1050 osid->Authority[5] = 5;
1051 osid->SubAuthorities[0] = cpu_to_le32(88);
1052 osid->SubAuthorities[1] = cpu_to_le32(1);
1053 osid->SubAuthorities[2] = cpu_to_le32(id);
1054 } else { /* lookup sid with upcall */
1055 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
1056 if (rc) {
1057 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
1058 __func__, rc, id);
1059 kfree(nowner_sid_ptr);
1060 return rc;
1061 }
1062 }
1063 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
1064 kfree(nowner_sid_ptr);
1065 *aclflag = CIFS_ACL_OWNER;
1066 }
1067 if (gid_valid(gid)) { /* chgrp */
1068 gid_t id;
1069 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1070 le32_to_cpu(pnntsd->gsidoffset));
1071 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1072 GFP_KERNEL);
1073 if (!ngroup_sid_ptr)
1074 return -ENOMEM;
1075 id = from_kgid(&init_user_ns, gid);
1076 if (id_from_sid) {
1077 struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
1078 /* Populate the group ownership fields S-1-5-88-2 */
1079 gsid->Revision = 1;
1080 gsid->NumAuth = 3;
1081 gsid->Authority[5] = 5;
1082 gsid->SubAuthorities[0] = cpu_to_le32(88);
1083 gsid->SubAuthorities[1] = cpu_to_le32(2);
1084 gsid->SubAuthorities[2] = cpu_to_le32(id);
1085 } else { /* lookup sid with upcall */
1086 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
1087 if (rc) {
1088 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
1089 __func__, rc, id);
1090 kfree(ngroup_sid_ptr);
1091 return rc;
1092 }
1093 }
1094 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
1095 kfree(ngroup_sid_ptr);
1096 *aclflag = CIFS_ACL_GROUP;
1097 }
1098 }
1099
1100 return rc;
1101 }
1102
get_cifs_acl_by_fid(struct cifs_sb_info * cifs_sb,const struct cifs_fid * cifsfid,u32 * pacllen)1103 struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1104 const struct cifs_fid *cifsfid, u32 *pacllen)
1105 {
1106 struct cifs_ntsd *pntsd = NULL;
1107 unsigned int xid;
1108 int rc;
1109 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1110
1111 if (IS_ERR(tlink))
1112 return ERR_CAST(tlink);
1113
1114 xid = get_xid();
1115 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1116 pacllen);
1117 free_xid(xid);
1118
1119 cifs_put_tlink(tlink);
1120
1121 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1122 if (rc)
1123 return ERR_PTR(rc);
1124 return pntsd;
1125 }
1126
get_cifs_acl_by_path(struct cifs_sb_info * cifs_sb,const char * path,u32 * pacllen)1127 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1128 const char *path, u32 *pacllen)
1129 {
1130 struct cifs_ntsd *pntsd = NULL;
1131 int oplock = 0;
1132 unsigned int xid;
1133 int rc;
1134 struct cifs_tcon *tcon;
1135 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1136 struct cifs_fid fid;
1137 struct cifs_open_parms oparms;
1138
1139 if (IS_ERR(tlink))
1140 return ERR_CAST(tlink);
1141
1142 tcon = tlink_tcon(tlink);
1143 xid = get_xid();
1144
1145 oparms.tcon = tcon;
1146 oparms.cifs_sb = cifs_sb;
1147 oparms.desired_access = READ_CONTROL;
1148 oparms.create_options = cifs_create_options(cifs_sb, 0);
1149 oparms.disposition = FILE_OPEN;
1150 oparms.path = path;
1151 oparms.fid = &fid;
1152 oparms.reconnect = false;
1153
1154 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1155 if (!rc) {
1156 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1157 CIFSSMBClose(xid, tcon, fid.netfid);
1158 }
1159
1160 cifs_put_tlink(tlink);
1161 free_xid(xid);
1162
1163 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1164 if (rc)
1165 return ERR_PTR(rc);
1166 return pntsd;
1167 }
1168
1169 /* Retrieve an ACL from the server */
get_cifs_acl(struct cifs_sb_info * cifs_sb,struct inode * inode,const char * path,u32 * pacllen)1170 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1171 struct inode *inode, const char *path,
1172 u32 *pacllen)
1173 {
1174 struct cifs_ntsd *pntsd = NULL;
1175 struct cifsFileInfo *open_file = NULL;
1176
1177 if (inode)
1178 open_file = find_readable_file(CIFS_I(inode), true);
1179 if (!open_file)
1180 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1181
1182 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1183 cifsFileInfo_put(open_file);
1184 return pntsd;
1185 }
1186
1187 /* Set an ACL on the server */
set_cifs_acl(struct cifs_ntsd * pnntsd,__u32 acllen,struct inode * inode,const char * path,int aclflag)1188 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1189 struct inode *inode, const char *path, int aclflag)
1190 {
1191 int oplock = 0;
1192 unsigned int xid;
1193 int rc, access_flags;
1194 struct cifs_tcon *tcon;
1195 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1196 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1197 struct cifs_fid fid;
1198 struct cifs_open_parms oparms;
1199
1200 if (IS_ERR(tlink))
1201 return PTR_ERR(tlink);
1202
1203 tcon = tlink_tcon(tlink);
1204 xid = get_xid();
1205
1206 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1207 access_flags = WRITE_OWNER;
1208 else
1209 access_flags = WRITE_DAC;
1210
1211 oparms.tcon = tcon;
1212 oparms.cifs_sb = cifs_sb;
1213 oparms.desired_access = access_flags;
1214 oparms.create_options = cifs_create_options(cifs_sb, 0);
1215 oparms.disposition = FILE_OPEN;
1216 oparms.path = path;
1217 oparms.fid = &fid;
1218 oparms.reconnect = false;
1219
1220 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1221 if (rc) {
1222 cifs_dbg(VFS, "Unable to open file to set ACL\n");
1223 goto out;
1224 }
1225
1226 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
1227 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
1228
1229 CIFSSMBClose(xid, tcon, fid.netfid);
1230 out:
1231 free_xid(xid);
1232 cifs_put_tlink(tlink);
1233 return rc;
1234 }
1235
1236 /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
1237 int
cifs_acl_to_fattr(struct cifs_sb_info * cifs_sb,struct cifs_fattr * fattr,struct inode * inode,bool mode_from_special_sid,const char * path,const struct cifs_fid * pfid)1238 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1239 struct inode *inode, bool mode_from_special_sid,
1240 const char *path, const struct cifs_fid *pfid)
1241 {
1242 struct cifs_ntsd *pntsd = NULL;
1243 u32 acllen = 0;
1244 int rc = 0;
1245 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1246 struct smb_version_operations *ops;
1247
1248 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1249
1250 if (IS_ERR(tlink))
1251 return PTR_ERR(tlink);
1252
1253 ops = tlink_tcon(tlink)->ses->server->ops;
1254
1255 if (pfid && (ops->get_acl_by_fid))
1256 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
1257 else if (ops->get_acl)
1258 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
1259 else {
1260 cifs_put_tlink(tlink);
1261 return -EOPNOTSUPP;
1262 }
1263 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1264 if (IS_ERR(pntsd)) {
1265 rc = PTR_ERR(pntsd);
1266 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1267 } else if (mode_from_special_sid) {
1268 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
1269 kfree(pntsd);
1270 } else {
1271 /* get approximated mode from ACL */
1272 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
1273 kfree(pntsd);
1274 if (rc)
1275 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1276 }
1277
1278 cifs_put_tlink(tlink);
1279
1280 return rc;
1281 }
1282
1283 /* Convert mode bits to an ACL so we can update the ACL on the server */
1284 int
id_mode_to_cifs_acl(struct inode * inode,const char * path,__u64 nmode,kuid_t uid,kgid_t gid)1285 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1286 kuid_t uid, kgid_t gid)
1287 {
1288 int rc = 0;
1289 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1290 __u32 secdesclen = 0;
1291 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1292 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1293 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1294 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1295 struct smb_version_operations *ops;
1296 bool mode_from_sid, id_from_sid;
1297
1298 if (IS_ERR(tlink))
1299 return PTR_ERR(tlink);
1300
1301 ops = tlink_tcon(tlink)->ses->server->ops;
1302
1303 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1304
1305 /* Get the security descriptor */
1306
1307 if (ops->get_acl == NULL) {
1308 cifs_put_tlink(tlink);
1309 return -EOPNOTSUPP;
1310 }
1311
1312 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
1313 if (IS_ERR(pntsd)) {
1314 rc = PTR_ERR(pntsd);
1315 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1316 cifs_put_tlink(tlink);
1317 return rc;
1318 }
1319
1320 /*
1321 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1322 * as chmod disables ACEs and set the security descriptor. Allocate
1323 * memory for the smb header, set security descriptor request security
1324 * descriptor parameters, and secuirty descriptor itself
1325 */
1326 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1327 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1328 if (!pnntsd) {
1329 kfree(pntsd);
1330 cifs_put_tlink(tlink);
1331 return -ENOMEM;
1332 }
1333
1334 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
1335 mode_from_sid = true;
1336 else
1337 mode_from_sid = false;
1338
1339 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
1340 id_from_sid = true;
1341 else
1342 id_from_sid = false;
1343
1344 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1345 mode_from_sid, id_from_sid, &aclflag);
1346
1347 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1348
1349 if (ops->set_acl == NULL)
1350 rc = -EOPNOTSUPP;
1351
1352 if (!rc) {
1353 /* Set the security descriptor */
1354 rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
1355 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1356 }
1357 cifs_put_tlink(tlink);
1358
1359 kfree(pnntsd);
1360 kfree(pntsd);
1361 return rc;
1362 }
1363