4 * Copyright (C) International Business Machines Corp., 2007,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for mapping CIFS/NTFS ACLs
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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>
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
36 static struct key_acl cifs_idmap_key_acl = {
37 .usage = REFCOUNT_INIT(1),
39 .possessor_viewable = true,
41 KEY_POSSESSOR_ACE(KEY_ACE_VIEW | KEY_ACE_SEARCH | KEY_ACE_READ),
42 KEY_OWNER_ACE(KEY_ACE_VIEW),
46 static struct key_acl cifs_idmap_keyring_acl = {
47 .usage = REFCOUNT_INIT(1),
50 KEY_POSSESSOR_ACE(KEY_ACE_SEARCH | KEY_ACE_WRITE),
51 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ),
55 /* security id for everyone/world system group */
56 static const struct cifs_sid sid_everyone = {
57 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
58 /* security id for Authenticated Users system group */
59 static const struct cifs_sid sid_authusers = {
60 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
62 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
64 /* S-1-22-1 Unmapped Unix users */
65 static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
66 {cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
68 /* S-1-22-2 Unmapped Unix groups */
69 static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
70 {cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
73 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
76 /* S-1-5-88 MS NFS and Apple style UID/GID/mode */
78 /* S-1-5-88-1 Unix uid */
79 static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
81 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
83 /* S-1-5-88-2 Unix gid */
84 static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
86 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
88 /* S-1-5-88-3 Unix mode */
89 static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
91 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
93 static const struct cred *root_cred;
96 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
101 * If the payload is less than or equal to the size of a pointer, then
102 * an allocation here is wasteful. Just copy the data directly to the
103 * payload.value union member instead.
105 * With this however, you must check the datalen before trying to
106 * dereference payload.data!
108 if (prep->datalen <= sizeof(key->payload)) {
109 key->payload.data[0] = NULL;
110 memcpy(&key->payload, prep->data, prep->datalen);
112 payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
115 key->payload.data[0] = payload;
118 key->datalen = prep->datalen;
123 cifs_idmap_key_destroy(struct key *key)
125 if (key->datalen > sizeof(key->payload))
126 kfree(key->payload.data[0]);
129 static struct key_type cifs_idmap_key_type = {
130 .name = "cifs.idmap",
131 .instantiate = cifs_idmap_key_instantiate,
132 .destroy = cifs_idmap_key_destroy,
133 .describe = user_describe,
137 sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
141 char *sidstr, *strptr;
142 unsigned long long id_auth_val;
144 /* 3 bytes for prefix */
145 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
146 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
152 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
156 /* The authority field is a single 48-bit number */
157 id_auth_val = (unsigned long long)sidptr->authority[5];
158 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
159 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
160 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
161 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
162 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
165 * MS-DTYP states that if the authority is >= 2^32, then it should be
166 * expressed as a hex value.
168 if (id_auth_val <= UINT_MAX)
169 len = sprintf(strptr, "-%llu", id_auth_val);
171 len = sprintf(strptr, "-0x%llx", id_auth_val);
175 for (i = 0; i < sidptr->num_subauth; ++i) {
176 saval = le32_to_cpu(sidptr->sub_auth[i]);
177 len = sprintf(strptr, "-%u", saval);
185 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
186 * the same returns zero, if they do not match returns non-zero.
189 compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
192 int num_subauth, num_sat, num_saw;
194 if ((!ctsid) || (!cwsid))
197 /* compare the revision */
198 if (ctsid->revision != cwsid->revision) {
199 if (ctsid->revision > cwsid->revision)
205 /* compare all of the six auth values */
206 for (i = 0; i < NUM_AUTHS; ++i) {
207 if (ctsid->authority[i] != cwsid->authority[i]) {
208 if (ctsid->authority[i] > cwsid->authority[i])
215 /* compare all of the subauth values if any */
216 num_sat = ctsid->num_subauth;
217 num_saw = cwsid->num_subauth;
218 num_subauth = num_sat < num_saw ? num_sat : num_saw;
220 for (i = 0; i < num_subauth; ++i) {
221 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
222 if (le32_to_cpu(ctsid->sub_auth[i]) >
223 le32_to_cpu(cwsid->sub_auth[i]))
231 return 0; /* sids compare/match */
235 is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
239 const struct cifs_sid *pwell_known_sid;
241 if (!psid || (puid == NULL))
244 num_subauth = psid->num_subauth;
246 /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
247 if (num_subauth == 2) {
249 pwell_known_sid = &sid_unix_groups;
251 pwell_known_sid = &sid_unix_users;
252 } else if (num_subauth == 3) {
254 pwell_known_sid = &sid_unix_NFS_groups;
256 pwell_known_sid = &sid_unix_NFS_users;
260 /* compare the revision */
261 if (psid->revision != pwell_known_sid->revision)
264 /* compare all of the six auth values */
265 for (i = 0; i < NUM_AUTHS; ++i) {
266 if (psid->authority[i] != pwell_known_sid->authority[i]) {
267 cifs_dbg(FYI, "auth %d did not match\n", i);
272 if (num_subauth == 2) {
273 if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
276 *puid = le32_to_cpu(psid->sub_auth[1]);
277 } else /* 3 subauths, ie Windows/Mac style */ {
278 *puid = le32_to_cpu(psid->sub_auth[0]);
279 if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
280 (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
283 *puid = le32_to_cpu(psid->sub_auth[2]);
286 cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
287 return true; /* well known sid found, uid returned */
291 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
295 dst->revision = src->revision;
296 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
297 for (i = 0; i < NUM_AUTHS; ++i)
298 dst->authority[i] = src->authority[i];
299 for (i = 0; i < dst->num_subauth; ++i)
300 dst->sub_auth[i] = src->sub_auth[i];
304 id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
308 struct cifs_sid *ksid;
309 unsigned int ksid_size;
310 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
311 const struct cred *saved_cred;
313 rc = snprintf(desc, sizeof(desc), "%ci:%u",
314 sidtype == SIDOWNER ? 'o' : 'g', cid);
315 if (rc >= sizeof(desc))
319 saved_cred = override_creds(root_cred);
320 sidkey = request_key(&cifs_idmap_key_type, desc, "",
321 &cifs_idmap_key_acl);
322 if (IS_ERR(sidkey)) {
324 cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
325 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
326 goto out_revert_creds;
327 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
329 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
330 __func__, sidkey->datalen);
335 * A sid is usually too large to be embedded in payload.value, but if
336 * there are no subauthorities and the host has 8-byte pointers, then
339 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
340 (struct cifs_sid *)&sidkey->payload :
341 (struct cifs_sid *)sidkey->payload.data[0];
343 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
344 if (ksid_size > sidkey->datalen) {
346 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
347 __func__, sidkey->datalen, ksid_size);
351 cifs_copy_sid(ssid, ksid);
355 revert_creds(saved_cred);
359 key_invalidate(sidkey);
364 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
365 struct cifs_fattr *fattr, uint sidtype)
370 const struct cred *saved_cred;
371 kuid_t fuid = cifs_sb->mnt_uid;
372 kgid_t fgid = cifs_sb->mnt_gid;
375 * If we have too many subauthorities, then something is really wrong.
376 * Just return an error.
378 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
379 cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
380 __func__, psid->num_subauth);
384 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
388 if (sidtype != SIDOWNER)
393 if (is_well_known_sid(psid, &unix_id, is_group) == false)
394 goto try_upcall_to_get_id;
401 gid = make_kgid(&init_user_ns, id);
402 if (gid_valid(gid)) {
411 uid = make_kuid(&init_user_ns, id);
412 if (uid_valid(uid)) {
417 /* If unable to find uid/gid easily from SID try via upcall */
420 try_upcall_to_get_id:
421 sidstr = sid_to_key_str(psid, sidtype);
425 saved_cred = override_creds(root_cred);
426 sidkey = request_key(&cifs_idmap_key_type, sidstr, "",
427 &cifs_idmap_key_acl);
428 if (IS_ERR(sidkey)) {
430 cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
431 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
432 goto out_revert_creds;
436 * FIXME: Here we assume that uid_t and gid_t are same size. It's
437 * probably a safe assumption but might be better to check based on
440 BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
441 if (sidkey->datalen != sizeof(uid_t)) {
443 cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
444 __func__, sidkey->datalen);
445 key_invalidate(sidkey);
449 if (sidtype == SIDOWNER) {
452 memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
453 uid = make_kuid(&init_user_ns, id);
459 memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
460 gid = make_kgid(&init_user_ns, id);
468 revert_creds(saved_cred);
472 * Note that we return 0 here unconditionally. If the mapping
473 * fails then we just fall back to using the mnt_uid/mnt_gid.
476 if (sidtype == SIDOWNER)
477 fattr->cf_uid = fuid;
479 fattr->cf_gid = fgid;
484 init_cifs_idmap(void)
490 cifs_dbg(FYI, "Registering the %s key type\n",
491 cifs_idmap_key_type.name);
493 /* create an override credential set with a special thread keyring in
494 * which requests are cached
496 * this is used to prevent malicious redirections from being installed
499 cred = prepare_kernel_cred(NULL);
503 keyring = keyring_alloc(".cifs_idmap",
504 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
505 &cifs_idmap_keyring_acl,
506 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
507 if (IS_ERR(keyring)) {
508 ret = PTR_ERR(keyring);
509 goto failed_put_cred;
512 ret = register_key_type(&cifs_idmap_key_type);
516 /* instruct request_key() to use this special keyring as a cache for
517 * the results it looks up */
518 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
519 cred->thread_keyring = keyring;
520 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
523 cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
534 exit_cifs_idmap(void)
536 key_revoke(root_cred->thread_keyring);
537 unregister_key_type(&cifs_idmap_key_type);
539 cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
542 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
543 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
544 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
546 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
547 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
549 /* copy security descriptor control portion */
550 pnntsd->revision = pntsd->revision;
551 pnntsd->type = pntsd->type;
552 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
553 pnntsd->sacloffset = 0;
554 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
555 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
558 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
559 le32_to_cpu(pntsd->osidoffset));
560 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
561 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
564 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
565 le32_to_cpu(pntsd->gsidoffset));
566 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
567 sizeof(struct cifs_sid));
568 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
575 change posix mode to reflect permissions
576 pmode is the existing mode (we only want to overwrite part of this
577 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
579 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
580 umode_t *pbits_to_set)
582 __u32 flags = le32_to_cpu(ace_flags);
583 /* the order of ACEs is important. The canonical order is to begin with
584 DENY entries followed by ALLOW, otherwise an allow entry could be
585 encountered first, making the subsequent deny entry like "dead code"
586 which would be superflous since Windows stops when a match is made
587 for the operation you are trying to perform for your user */
589 /* For deny ACEs we change the mask so that subsequent allow access
590 control entries do not turn on the bits we are denying */
591 if (type == ACCESS_DENIED) {
592 if (flags & GENERIC_ALL)
593 *pbits_to_set &= ~S_IRWXUGO;
595 if ((flags & GENERIC_WRITE) ||
596 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
597 *pbits_to_set &= ~S_IWUGO;
598 if ((flags & GENERIC_READ) ||
599 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
600 *pbits_to_set &= ~S_IRUGO;
601 if ((flags & GENERIC_EXECUTE) ||
602 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
603 *pbits_to_set &= ~S_IXUGO;
605 } else if (type != ACCESS_ALLOWED) {
606 cifs_dbg(VFS, "unknown access control type %d\n", type);
609 /* else ACCESS_ALLOWED type */
611 if (flags & GENERIC_ALL) {
612 *pmode |= (S_IRWXUGO & (*pbits_to_set));
613 cifs_dbg(NOISY, "all perms\n");
616 if ((flags & GENERIC_WRITE) ||
617 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
618 *pmode |= (S_IWUGO & (*pbits_to_set));
619 if ((flags & GENERIC_READ) ||
620 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
621 *pmode |= (S_IRUGO & (*pbits_to_set));
622 if ((flags & GENERIC_EXECUTE) ||
623 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
624 *pmode |= (S_IXUGO & (*pbits_to_set));
626 cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
631 Generate access flags to reflect permissions mode is the existing mode.
632 This function is called for every ACE in the DACL whose SID matches
633 with either owner or group or everyone.
636 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
639 /* reset access mask */
642 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
645 /* check for R/W/X UGO since we do not know whose flags
646 is this but we have cleared all the bits sans RWX for
647 either user or group or other as per bits_to_use */
649 *pace_flags |= SET_FILE_READ_RIGHTS;
651 *pace_flags |= SET_FILE_WRITE_RIGHTS;
653 *pace_flags |= SET_FILE_EXEC_RIGHTS;
655 cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
660 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
661 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
665 __u32 access_req = 0;
667 pntace->type = ACCESS_ALLOWED;
669 mode_to_access_flags(nmode, bits, &access_req);
671 access_req = SET_MINIMUM_RIGHTS;
672 pntace->access_req = cpu_to_le32(access_req);
674 pntace->sid.revision = psid->revision;
675 pntace->sid.num_subauth = psid->num_subauth;
676 for (i = 0; i < NUM_AUTHS; i++)
677 pntace->sid.authority[i] = psid->authority[i];
678 for (i = 0; i < psid->num_subauth; i++)
679 pntace->sid.sub_auth[i] = psid->sub_auth[i];
681 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
682 pntace->size = cpu_to_le16(size);
688 #ifdef CONFIG_CIFS_DEBUG2
689 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
693 /* validate that we do not go past end of acl */
695 if (le16_to_cpu(pace->size) < 16) {
696 cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
700 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
701 cifs_dbg(VFS, "ACL too small to parse ACE\n");
705 num_subauth = pace->sid.num_subauth;
708 cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
709 pace->sid.revision, pace->sid.num_subauth, pace->type,
710 pace->flags, le16_to_cpu(pace->size));
711 for (i = 0; i < num_subauth; ++i) {
712 cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
713 i, le32_to_cpu(pace->sid.sub_auth[i]));
716 /* BB add length check to make sure that we do not have huge
717 num auths and therefore go off the end */
725 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
726 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
727 struct cifs_fattr *fattr)
733 struct cifs_ace **ppace;
735 /* BB need to add parm so we can store the SID BB */
738 /* no DACL in the security descriptor, set
739 all the permissions for user/group/other */
740 fattr->cf_mode |= S_IRWXUGO;
744 /* validate that we do not go past end of acl */
745 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
746 cifs_dbg(VFS, "ACL too small to parse DACL\n");
750 cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
751 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
752 le32_to_cpu(pdacl->num_aces));
754 /* reset rwx permissions for user/group/other.
755 Also, if num_aces is 0 i.e. DACL has no ACEs,
756 user/group/other have no permissions */
757 fattr->cf_mode &= ~(S_IRWXUGO);
759 acl_base = (char *)pdacl;
760 acl_size = sizeof(struct cifs_acl);
762 num_aces = le32_to_cpu(pdacl->num_aces);
764 umode_t user_mask = S_IRWXU;
765 umode_t group_mask = S_IRWXG;
766 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
768 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
770 ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
775 for (i = 0; i < num_aces; ++i) {
776 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
777 #ifdef CONFIG_CIFS_DEBUG2
778 dump_ace(ppace[i], end_of_acl);
780 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
781 access_flags_to_mode(ppace[i]->access_req,
785 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
786 access_flags_to_mode(ppace[i]->access_req,
790 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
791 access_flags_to_mode(ppace[i]->access_req,
795 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
796 access_flags_to_mode(ppace[i]->access_req,
802 /* memcpy((void *)(&(cifscred->aces[i])),
804 sizeof(struct cifs_ace)); */
806 acl_base = (char *)ppace[i];
807 acl_size = le16_to_cpu(ppace[i]->size);
817 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
818 struct cifs_sid *pgrpsid, __u64 nmode)
821 struct cifs_acl *pnndacl;
823 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
825 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
826 pownersid, nmode, S_IRWXU);
827 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
828 pgrpsid, nmode, S_IRWXG);
829 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
830 &sid_everyone, nmode, S_IRWXO);
832 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
833 pndacl->num_aces = cpu_to_le32(3);
839 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
841 /* BB need to add parm so we can store the SID BB */
843 /* validate that we do not go past end of ACL - sid must be at least 8
844 bytes long (assuming no sub-auths - e.g. the null SID */
845 if (end_of_acl < (char *)psid + 8) {
846 cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
850 #ifdef CONFIG_CIFS_DEBUG2
851 if (psid->num_subauth) {
853 cifs_dbg(FYI, "SID revision %d num_auth %d\n",
854 psid->revision, psid->num_subauth);
856 for (i = 0; i < psid->num_subauth; i++) {
857 cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
858 i, le32_to_cpu(psid->sub_auth[i]));
861 /* BB add length check to make sure that we do not have huge
862 num auths and therefore go off the end */
863 cifs_dbg(FYI, "RID 0x%x\n",
864 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
872 /* Convert CIFS ACL to POSIX form */
873 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
874 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
877 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
878 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
879 char *end_of_acl = ((char *)pntsd) + acl_len;
885 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
886 le32_to_cpu(pntsd->osidoffset));
887 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
888 le32_to_cpu(pntsd->gsidoffset));
889 dacloffset = le32_to_cpu(pntsd->dacloffset);
890 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
891 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
892 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
893 le32_to_cpu(pntsd->gsidoffset),
894 le32_to_cpu(pntsd->sacloffset), dacloffset);
895 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
896 rc = parse_sid(owner_sid_ptr, end_of_acl);
898 cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
901 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
903 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
908 rc = parse_sid(group_sid_ptr, end_of_acl);
910 cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
914 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
916 cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
922 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
923 group_sid_ptr, fattr);
925 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
930 /* Convert permission bits from mode to equivalent CIFS ACL */
931 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
932 __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
938 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
939 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
940 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
941 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
943 if (nmode != NO_CHANGE_64) { /* chmod */
944 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
945 le32_to_cpu(pntsd->osidoffset));
946 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
947 le32_to_cpu(pntsd->gsidoffset));
948 dacloffset = le32_to_cpu(pntsd->dacloffset);
949 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
950 ndacloffset = sizeof(struct cifs_ntsd);
951 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
952 ndacl_ptr->revision = dacl_ptr->revision;
954 ndacl_ptr->num_aces = 0;
956 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
958 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
959 /* copy sec desc control portion & owner and group sids */
960 copy_sec_desc(pntsd, pnntsd, sidsoffset);
961 *aclflag = CIFS_ACL_DACL;
963 memcpy(pnntsd, pntsd, secdesclen);
964 if (uid_valid(uid)) { /* chown */
966 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
967 le32_to_cpu(pnntsd->osidoffset));
968 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
972 id = from_kuid(&init_user_ns, uid);
973 rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
975 cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
977 kfree(nowner_sid_ptr);
980 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
981 kfree(nowner_sid_ptr);
982 *aclflag = CIFS_ACL_OWNER;
984 if (gid_valid(gid)) { /* chgrp */
986 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
987 le32_to_cpu(pnntsd->gsidoffset));
988 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
992 id = from_kgid(&init_user_ns, gid);
993 rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
995 cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
997 kfree(ngroup_sid_ptr);
1000 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
1001 kfree(ngroup_sid_ptr);
1002 *aclflag = CIFS_ACL_GROUP;
1009 struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1010 const struct cifs_fid *cifsfid, u32 *pacllen)
1012 struct cifs_ntsd *pntsd = NULL;
1015 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1018 return ERR_CAST(tlink);
1021 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1025 cifs_put_tlink(tlink);
1027 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1033 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1034 const char *path, u32 *pacllen)
1036 struct cifs_ntsd *pntsd = NULL;
1039 int rc, create_options = 0;
1040 struct cifs_tcon *tcon;
1041 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1042 struct cifs_fid fid;
1043 struct cifs_open_parms oparms;
1046 return ERR_CAST(tlink);
1048 tcon = tlink_tcon(tlink);
1051 if (backup_cred(cifs_sb))
1052 create_options |= CREATE_OPEN_BACKUP_INTENT;
1055 oparms.cifs_sb = cifs_sb;
1056 oparms.desired_access = READ_CONTROL;
1057 oparms.create_options = create_options;
1058 oparms.disposition = FILE_OPEN;
1061 oparms.reconnect = false;
1063 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1065 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1066 CIFSSMBClose(xid, tcon, fid.netfid);
1069 cifs_put_tlink(tlink);
1072 cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1078 /* Retrieve an ACL from the server */
1079 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1080 struct inode *inode, const char *path,
1083 struct cifs_ntsd *pntsd = NULL;
1084 struct cifsFileInfo *open_file = NULL;
1087 open_file = find_readable_file(CIFS_I(inode), true);
1089 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1091 pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1092 cifsFileInfo_put(open_file);
1096 /* Set an ACL on the server */
1097 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1098 struct inode *inode, const char *path, int aclflag)
1102 int rc, access_flags, create_options = 0;
1103 struct cifs_tcon *tcon;
1104 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1105 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1106 struct cifs_fid fid;
1107 struct cifs_open_parms oparms;
1110 return PTR_ERR(tlink);
1112 tcon = tlink_tcon(tlink);
1115 if (backup_cred(cifs_sb))
1116 create_options |= CREATE_OPEN_BACKUP_INTENT;
1118 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1119 access_flags = WRITE_OWNER;
1121 access_flags = WRITE_DAC;
1124 oparms.cifs_sb = cifs_sb;
1125 oparms.desired_access = access_flags;
1126 oparms.create_options = create_options;
1127 oparms.disposition = FILE_OPEN;
1130 oparms.reconnect = false;
1132 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1134 cifs_dbg(VFS, "Unable to open file to set ACL\n");
1138 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
1139 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
1141 CIFSSMBClose(xid, tcon, fid.netfid);
1144 cifs_put_tlink(tlink);
1148 /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
1150 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1151 struct inode *inode, const char *path,
1152 const struct cifs_fid *pfid)
1154 struct cifs_ntsd *pntsd = NULL;
1157 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1158 struct smb_version_operations *ops;
1160 cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1163 return PTR_ERR(tlink);
1165 ops = tlink_tcon(tlink)->ses->server->ops;
1167 if (pfid && (ops->get_acl_by_fid))
1168 pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
1169 else if (ops->get_acl)
1170 pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
1172 cifs_put_tlink(tlink);
1175 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1176 if (IS_ERR(pntsd)) {
1177 rc = PTR_ERR(pntsd);
1178 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1180 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1183 cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1186 cifs_put_tlink(tlink);
1191 /* Convert mode bits to an ACL so we can update the ACL on the server */
1193 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1194 kuid_t uid, kgid_t gid)
1197 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1198 __u32 secdesclen = 0;
1199 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1200 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1201 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1202 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1203 struct smb_version_operations *ops;
1206 return PTR_ERR(tlink);
1208 ops = tlink_tcon(tlink)->ses->server->ops;
1210 cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1212 /* Get the security descriptor */
1214 if (ops->get_acl == NULL) {
1215 cifs_put_tlink(tlink);
1219 pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
1220 if (IS_ERR(pntsd)) {
1221 rc = PTR_ERR(pntsd);
1222 cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1223 cifs_put_tlink(tlink);
1228 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1229 * as chmod disables ACEs and set the security descriptor. Allocate
1230 * memory for the smb header, set security descriptor request security
1231 * descriptor parameters, and secuirty descriptor itself
1233 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1234 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1237 cifs_put_tlink(tlink);
1241 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1244 cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1246 if (ops->set_acl == NULL)
1250 /* Set the security descriptor */
1251 rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
1252 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1254 cifs_put_tlink(tlink);