pinctrl/lantiq: add functionality to falcon_pinconf_dbg_show
[linux-2.6.git] / fs / cifs / cifsacl.c
blob5cbd00e740671dc13a0f4a07621513eb469762ac
1 /*
2 * fs/cifs/cifsacl.c
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
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"
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}, {__constant_cpu_to_le32(11)} };
42 /* group users */
43 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
45 static const struct cred *root_cred;
47 static int
48 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
50 char *payload;
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.
57 * With this however, you must check the datalen before trying to
58 * dereference payload.data!
60 if (prep->datalen <= sizeof(key->payload)) {
61 key->payload.value = 0;
62 memcpy(&key->payload.value, prep->data, prep->datalen);
63 key->datalen = prep->datalen;
64 return 0;
66 payload = kmalloc(prep->datalen, GFP_KERNEL);
67 if (!payload)
68 return -ENOMEM;
70 memcpy(payload, prep->data, prep->datalen);
71 key->payload.data = payload;
72 key->datalen = prep->datalen;
73 return 0;
76 static inline void
77 cifs_idmap_key_destroy(struct key *key)
79 if (key->datalen > sizeof(key->payload))
80 kfree(key->payload.data);
83 static struct key_type cifs_idmap_key_type = {
84 .name = "cifs.idmap",
85 .instantiate = cifs_idmap_key_instantiate,
86 .destroy = cifs_idmap_key_destroy,
87 .describe = user_describe,
88 .match = user_match,
91 static char *
92 sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
94 int i, len;
95 unsigned int saval;
96 char *sidstr, *strptr;
97 unsigned long long id_auth_val;
99 /* 3 bytes for prefix */
100 sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
101 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
102 GFP_KERNEL);
103 if (!sidstr)
104 return sidstr;
106 strptr = sidstr;
107 len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
108 sidptr->revision);
109 strptr += len;
111 /* The authority field is a single 48-bit number */
112 id_auth_val = (unsigned long long)sidptr->authority[5];
113 id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
114 id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
115 id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
116 id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
117 id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
120 * MS-DTYP states that if the authority is >= 2^32, then it should be
121 * expressed as a hex value.
123 if (id_auth_val <= UINT_MAX)
124 len = sprintf(strptr, "-%llu", id_auth_val);
125 else
126 len = sprintf(strptr, "-0x%llx", id_auth_val);
128 strptr += len;
130 for (i = 0; i < sidptr->num_subauth; ++i) {
131 saval = le32_to_cpu(sidptr->sub_auth[i]);
132 len = sprintf(strptr, "-%u", saval);
133 strptr += len;
136 return sidstr;
140 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
141 * the same returns zero, if they do not match returns non-zero.
143 static int
144 compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
146 int i;
147 int num_subauth, num_sat, num_saw;
149 if ((!ctsid) || (!cwsid))
150 return 1;
152 /* compare the revision */
153 if (ctsid->revision != cwsid->revision) {
154 if (ctsid->revision > cwsid->revision)
155 return 1;
156 else
157 return -1;
160 /* compare all of the six auth values */
161 for (i = 0; i < NUM_AUTHS; ++i) {
162 if (ctsid->authority[i] != cwsid->authority[i]) {
163 if (ctsid->authority[i] > cwsid->authority[i])
164 return 1;
165 else
166 return -1;
170 /* compare all of the subauth values if any */
171 num_sat = ctsid->num_subauth;
172 num_saw = cwsid->num_subauth;
173 num_subauth = num_sat < num_saw ? num_sat : num_saw;
174 if (num_subauth) {
175 for (i = 0; i < num_subauth; ++i) {
176 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
177 if (le32_to_cpu(ctsid->sub_auth[i]) >
178 le32_to_cpu(cwsid->sub_auth[i]))
179 return 1;
180 else
181 return -1;
186 return 0; /* sids compare/match */
189 static void
190 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
192 int i;
194 dst->revision = src->revision;
195 dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
196 for (i = 0; i < NUM_AUTHS; ++i)
197 dst->authority[i] = src->authority[i];
198 for (i = 0; i < dst->num_subauth; ++i)
199 dst->sub_auth[i] = src->sub_auth[i];
202 static int
203 id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
205 int rc;
206 struct key *sidkey;
207 struct cifs_sid *ksid;
208 unsigned int ksid_size;
209 char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
210 const struct cred *saved_cred;
212 rc = snprintf(desc, sizeof(desc), "%ci:%u",
213 sidtype == SIDOWNER ? 'o' : 'g', cid);
214 if (rc >= sizeof(desc))
215 return -EINVAL;
217 rc = 0;
218 saved_cred = override_creds(root_cred);
219 sidkey = request_key(&cifs_idmap_key_type, desc, "");
220 if (IS_ERR(sidkey)) {
221 rc = -EINVAL;
222 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
223 sidtype == SIDOWNER ? 'u' : 'g', cid);
224 goto out_revert_creds;
225 } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
226 rc = -EIO;
227 cFYI(1, "%s: Downcall contained malformed key "
228 "(datalen=%hu)", __func__, sidkey->datalen);
229 goto invalidate_key;
233 * A sid is usually too large to be embedded in payload.value, but if
234 * there are no subauthorities and the host has 8-byte pointers, then
235 * it could be.
237 ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
238 (struct cifs_sid *)&sidkey->payload.value :
239 (struct cifs_sid *)sidkey->payload.data;
241 ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
242 if (ksid_size > sidkey->datalen) {
243 rc = -EIO;
244 cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
245 "ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
246 goto invalidate_key;
249 cifs_copy_sid(ssid, ksid);
250 out_key_put:
251 key_put(sidkey);
252 out_revert_creds:
253 revert_creds(saved_cred);
254 return rc;
256 invalidate_key:
257 key_invalidate(sidkey);
258 goto out_key_put;
261 static int
262 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
263 struct cifs_fattr *fattr, uint sidtype)
265 int rc;
266 struct key *sidkey;
267 char *sidstr;
268 const struct cred *saved_cred;
269 uid_t fuid = cifs_sb->mnt_uid;
270 gid_t fgid = cifs_sb->mnt_gid;
273 * If we have too many subauthorities, then something is really wrong.
274 * Just return an error.
276 if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
277 cFYI(1, "%s: %u subauthorities is too many!", __func__,
278 psid->num_subauth);
279 return -EIO;
282 sidstr = sid_to_key_str(psid, sidtype);
283 if (!sidstr)
284 return -ENOMEM;
286 saved_cred = override_creds(root_cred);
287 sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
288 if (IS_ERR(sidkey)) {
289 rc = -EINVAL;
290 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
291 sidtype == SIDOWNER ? 'u' : 'g');
292 goto out_revert_creds;
296 * FIXME: Here we assume that uid_t and gid_t are same size. It's
297 * probably a safe assumption but might be better to check based on
298 * sidtype.
300 if (sidkey->datalen != sizeof(uid_t)) {
301 rc = -EIO;
302 cFYI(1, "%s: Downcall contained malformed key "
303 "(datalen=%hu)", __func__, sidkey->datalen);
304 key_invalidate(sidkey);
305 goto out_key_put;
308 if (sidtype == SIDOWNER)
309 memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
310 else
311 memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
313 out_key_put:
314 key_put(sidkey);
315 out_revert_creds:
316 revert_creds(saved_cred);
317 kfree(sidstr);
320 * Note that we return 0 here unconditionally. If the mapping
321 * fails then we just fall back to using the mnt_uid/mnt_gid.
323 if (sidtype == SIDOWNER)
324 fattr->cf_uid = fuid;
325 else
326 fattr->cf_gid = fgid;
327 return 0;
331 init_cifs_idmap(void)
333 struct cred *cred;
334 struct key *keyring;
335 int ret;
337 cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
339 /* create an override credential set with a special thread keyring in
340 * which requests are cached
342 * this is used to prevent malicious redirections from being installed
343 * with add_key().
345 cred = prepare_kernel_cred(NULL);
346 if (!cred)
347 return -ENOMEM;
349 keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
350 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
351 KEY_USR_VIEW | KEY_USR_READ,
352 KEY_ALLOC_NOT_IN_QUOTA, NULL);
353 if (IS_ERR(keyring)) {
354 ret = PTR_ERR(keyring);
355 goto failed_put_cred;
358 ret = register_key_type(&cifs_idmap_key_type);
359 if (ret < 0)
360 goto failed_put_key;
362 /* instruct request_key() to use this special keyring as a cache for
363 * the results it looks up */
364 set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
365 cred->thread_keyring = keyring;
366 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
367 root_cred = cred;
369 cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
370 return 0;
372 failed_put_key:
373 key_put(keyring);
374 failed_put_cred:
375 put_cred(cred);
376 return ret;
379 void
380 exit_cifs_idmap(void)
382 key_revoke(root_cred->thread_keyring);
383 unregister_key_type(&cifs_idmap_key_type);
384 put_cred(root_cred);
385 cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
388 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
389 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
390 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
392 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
393 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
395 /* copy security descriptor control portion */
396 pnntsd->revision = pntsd->revision;
397 pnntsd->type = pntsd->type;
398 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
399 pnntsd->sacloffset = 0;
400 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
401 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
403 /* copy owner sid */
404 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
405 le32_to_cpu(pntsd->osidoffset));
406 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
407 cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
409 /* copy group sid */
410 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
411 le32_to_cpu(pntsd->gsidoffset));
412 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
413 sizeof(struct cifs_sid));
414 cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
416 return;
421 change posix mode to reflect permissions
422 pmode is the existing mode (we only want to overwrite part of this
423 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
425 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
426 umode_t *pbits_to_set)
428 __u32 flags = le32_to_cpu(ace_flags);
429 /* the order of ACEs is important. The canonical order is to begin with
430 DENY entries followed by ALLOW, otherwise an allow entry could be
431 encountered first, making the subsequent deny entry like "dead code"
432 which would be superflous since Windows stops when a match is made
433 for the operation you are trying to perform for your user */
435 /* For deny ACEs we change the mask so that subsequent allow access
436 control entries do not turn on the bits we are denying */
437 if (type == ACCESS_DENIED) {
438 if (flags & GENERIC_ALL)
439 *pbits_to_set &= ~S_IRWXUGO;
441 if ((flags & GENERIC_WRITE) ||
442 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
443 *pbits_to_set &= ~S_IWUGO;
444 if ((flags & GENERIC_READ) ||
445 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
446 *pbits_to_set &= ~S_IRUGO;
447 if ((flags & GENERIC_EXECUTE) ||
448 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
449 *pbits_to_set &= ~S_IXUGO;
450 return;
451 } else if (type != ACCESS_ALLOWED) {
452 cERROR(1, "unknown access control type %d", type);
453 return;
455 /* else ACCESS_ALLOWED type */
457 if (flags & GENERIC_ALL) {
458 *pmode |= (S_IRWXUGO & (*pbits_to_set));
459 cFYI(DBG2, "all perms");
460 return;
462 if ((flags & GENERIC_WRITE) ||
463 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
464 *pmode |= (S_IWUGO & (*pbits_to_set));
465 if ((flags & GENERIC_READ) ||
466 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
467 *pmode |= (S_IRUGO & (*pbits_to_set));
468 if ((flags & GENERIC_EXECUTE) ||
469 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
470 *pmode |= (S_IXUGO & (*pbits_to_set));
472 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
473 return;
477 Generate access flags to reflect permissions mode is the existing mode.
478 This function is called for every ACE in the DACL whose SID matches
479 with either owner or group or everyone.
482 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
483 __u32 *pace_flags)
485 /* reset access mask */
486 *pace_flags = 0x0;
488 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
489 mode &= bits_to_use;
491 /* check for R/W/X UGO since we do not know whose flags
492 is this but we have cleared all the bits sans RWX for
493 either user or group or other as per bits_to_use */
494 if (mode & S_IRUGO)
495 *pace_flags |= SET_FILE_READ_RIGHTS;
496 if (mode & S_IWUGO)
497 *pace_flags |= SET_FILE_WRITE_RIGHTS;
498 if (mode & S_IXUGO)
499 *pace_flags |= SET_FILE_EXEC_RIGHTS;
501 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
502 return;
505 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
506 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
508 int i;
509 __u16 size = 0;
510 __u32 access_req = 0;
512 pntace->type = ACCESS_ALLOWED;
513 pntace->flags = 0x0;
514 mode_to_access_flags(nmode, bits, &access_req);
515 if (!access_req)
516 access_req = SET_MINIMUM_RIGHTS;
517 pntace->access_req = cpu_to_le32(access_req);
519 pntace->sid.revision = psid->revision;
520 pntace->sid.num_subauth = psid->num_subauth;
521 for (i = 0; i < NUM_AUTHS; i++)
522 pntace->sid.authority[i] = psid->authority[i];
523 for (i = 0; i < psid->num_subauth; i++)
524 pntace->sid.sub_auth[i] = psid->sub_auth[i];
526 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
527 pntace->size = cpu_to_le16(size);
529 return size;
533 #ifdef CONFIG_CIFS_DEBUG2
534 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
536 int num_subauth;
538 /* validate that we do not go past end of acl */
540 if (le16_to_cpu(pace->size) < 16) {
541 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
542 return;
545 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
546 cERROR(1, "ACL too small to parse ACE");
547 return;
550 num_subauth = pace->sid.num_subauth;
551 if (num_subauth) {
552 int i;
553 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
554 pace->sid.revision, pace->sid.num_subauth, pace->type,
555 pace->flags, le16_to_cpu(pace->size));
556 for (i = 0; i < num_subauth; ++i) {
557 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
558 le32_to_cpu(pace->sid.sub_auth[i]));
561 /* BB add length check to make sure that we do not have huge
562 num auths and therefore go off the end */
565 return;
567 #endif
570 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
571 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
572 struct cifs_fattr *fattr)
574 int i;
575 int num_aces = 0;
576 int acl_size;
577 char *acl_base;
578 struct cifs_ace **ppace;
580 /* BB need to add parm so we can store the SID BB */
582 if (!pdacl) {
583 /* no DACL in the security descriptor, set
584 all the permissions for user/group/other */
585 fattr->cf_mode |= S_IRWXUGO;
586 return;
589 /* validate that we do not go past end of acl */
590 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
591 cERROR(1, "ACL too small to parse DACL");
592 return;
595 cFYI(DBG2, "DACL revision %d size %d num aces %d",
596 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
597 le32_to_cpu(pdacl->num_aces));
599 /* reset rwx permissions for user/group/other.
600 Also, if num_aces is 0 i.e. DACL has no ACEs,
601 user/group/other have no permissions */
602 fattr->cf_mode &= ~(S_IRWXUGO);
604 acl_base = (char *)pdacl;
605 acl_size = sizeof(struct cifs_acl);
607 num_aces = le32_to_cpu(pdacl->num_aces);
608 if (num_aces > 0) {
609 umode_t user_mask = S_IRWXU;
610 umode_t group_mask = S_IRWXG;
611 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
613 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
614 return;
615 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
616 GFP_KERNEL);
617 if (!ppace) {
618 cERROR(1, "DACL memory allocation error");
619 return;
622 for (i = 0; i < num_aces; ++i) {
623 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
624 #ifdef CONFIG_CIFS_DEBUG2
625 dump_ace(ppace[i], end_of_acl);
626 #endif
627 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
628 access_flags_to_mode(ppace[i]->access_req,
629 ppace[i]->type,
630 &fattr->cf_mode,
631 &user_mask);
632 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
633 access_flags_to_mode(ppace[i]->access_req,
634 ppace[i]->type,
635 &fattr->cf_mode,
636 &group_mask);
637 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
638 access_flags_to_mode(ppace[i]->access_req,
639 ppace[i]->type,
640 &fattr->cf_mode,
641 &other_mask);
642 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
643 access_flags_to_mode(ppace[i]->access_req,
644 ppace[i]->type,
645 &fattr->cf_mode,
646 &other_mask);
649 /* memcpy((void *)(&(cifscred->aces[i])),
650 (void *)ppace[i],
651 sizeof(struct cifs_ace)); */
653 acl_base = (char *)ppace[i];
654 acl_size = le16_to_cpu(ppace[i]->size);
657 kfree(ppace);
660 return;
664 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
665 struct cifs_sid *pgrpsid, __u64 nmode)
667 u16 size = 0;
668 struct cifs_acl *pnndacl;
670 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
672 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
673 pownersid, nmode, S_IRWXU);
674 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
675 pgrpsid, nmode, S_IRWXG);
676 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
677 &sid_everyone, nmode, S_IRWXO);
679 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
680 pndacl->num_aces = cpu_to_le32(3);
682 return 0;
686 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
688 /* BB need to add parm so we can store the SID BB */
690 /* validate that we do not go past end of ACL - sid must be at least 8
691 bytes long (assuming no sub-auths - e.g. the null SID */
692 if (end_of_acl < (char *)psid + 8) {
693 cERROR(1, "ACL too small to parse SID %p", psid);
694 return -EINVAL;
697 #ifdef CONFIG_CIFS_DEBUG2
698 if (psid->num_subauth) {
699 int i;
700 cFYI(1, "SID revision %d num_auth %d",
701 psid->revision, psid->num_subauth);
703 for (i = 0; i < psid->num_subauth; i++) {
704 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
705 le32_to_cpu(psid->sub_auth[i]));
708 /* BB add length check to make sure that we do not have huge
709 num auths and therefore go off the end */
710 cFYI(1, "RID 0x%x",
711 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
713 #endif
715 return 0;
719 /* Convert CIFS ACL to POSIX form */
720 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
721 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
723 int rc = 0;
724 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
725 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
726 char *end_of_acl = ((char *)pntsd) + acl_len;
727 __u32 dacloffset;
729 if (pntsd == NULL)
730 return -EIO;
732 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
733 le32_to_cpu(pntsd->osidoffset));
734 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
735 le32_to_cpu(pntsd->gsidoffset));
736 dacloffset = le32_to_cpu(pntsd->dacloffset);
737 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
738 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
739 "sacloffset 0x%x dacloffset 0x%x",
740 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
741 le32_to_cpu(pntsd->gsidoffset),
742 le32_to_cpu(pntsd->sacloffset), dacloffset);
743 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
744 rc = parse_sid(owner_sid_ptr, end_of_acl);
745 if (rc) {
746 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
747 return rc;
749 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
750 if (rc) {
751 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
752 return rc;
755 rc = parse_sid(group_sid_ptr, end_of_acl);
756 if (rc) {
757 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
758 return rc;
760 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
761 if (rc) {
762 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
763 return rc;
766 if (dacloffset)
767 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
768 group_sid_ptr, fattr);
769 else
770 cFYI(1, "no ACL"); /* BB grant all or default perms? */
772 return rc;
775 /* Convert permission bits from mode to equivalent CIFS ACL */
776 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
777 __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
779 int rc = 0;
780 __u32 dacloffset;
781 __u32 ndacloffset;
782 __u32 sidsoffset;
783 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
784 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
785 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
786 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
788 if (nmode != NO_CHANGE_64) { /* chmod */
789 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
790 le32_to_cpu(pntsd->osidoffset));
791 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
792 le32_to_cpu(pntsd->gsidoffset));
793 dacloffset = le32_to_cpu(pntsd->dacloffset);
794 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
795 ndacloffset = sizeof(struct cifs_ntsd);
796 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
797 ndacl_ptr->revision = dacl_ptr->revision;
798 ndacl_ptr->size = 0;
799 ndacl_ptr->num_aces = 0;
801 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
802 nmode);
803 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
804 /* copy sec desc control portion & owner and group sids */
805 copy_sec_desc(pntsd, pnntsd, sidsoffset);
806 *aclflag = CIFS_ACL_DACL;
807 } else {
808 memcpy(pnntsd, pntsd, secdesclen);
809 if (uid != NO_CHANGE_32) { /* chown */
810 owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
811 le32_to_cpu(pnntsd->osidoffset));
812 nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
813 GFP_KERNEL);
814 if (!nowner_sid_ptr)
815 return -ENOMEM;
816 rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
817 if (rc) {
818 cFYI(1, "%s: Mapping error %d for owner id %d",
819 __func__, rc, uid);
820 kfree(nowner_sid_ptr);
821 return rc;
823 cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
824 kfree(nowner_sid_ptr);
825 *aclflag = CIFS_ACL_OWNER;
827 if (gid != NO_CHANGE_32) { /* chgrp */
828 group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
829 le32_to_cpu(pnntsd->gsidoffset));
830 ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
831 GFP_KERNEL);
832 if (!ngroup_sid_ptr)
833 return -ENOMEM;
834 rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
835 if (rc) {
836 cFYI(1, "%s: Mapping error %d for group id %d",
837 __func__, rc, gid);
838 kfree(ngroup_sid_ptr);
839 return rc;
841 cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
842 kfree(ngroup_sid_ptr);
843 *aclflag = CIFS_ACL_GROUP;
847 return rc;
850 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
851 __u16 fid, u32 *pacllen)
853 struct cifs_ntsd *pntsd = NULL;
854 unsigned int xid;
855 int rc;
856 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
858 if (IS_ERR(tlink))
859 return ERR_CAST(tlink);
861 xid = get_xid();
862 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
863 free_xid(xid);
865 cifs_put_tlink(tlink);
867 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
868 if (rc)
869 return ERR_PTR(rc);
870 return pntsd;
873 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
874 const char *path, u32 *pacllen)
876 struct cifs_ntsd *pntsd = NULL;
877 int oplock = 0;
878 unsigned int xid;
879 int rc, create_options = 0;
880 __u16 fid;
881 struct cifs_tcon *tcon;
882 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
884 if (IS_ERR(tlink))
885 return ERR_CAST(tlink);
887 tcon = tlink_tcon(tlink);
888 xid = get_xid();
890 if (backup_cred(cifs_sb))
891 create_options |= CREATE_OPEN_BACKUP_INTENT;
893 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
894 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
895 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
896 if (!rc) {
897 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
898 CIFSSMBClose(xid, tcon, fid);
901 cifs_put_tlink(tlink);
902 free_xid(xid);
904 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
905 if (rc)
906 return ERR_PTR(rc);
907 return pntsd;
910 /* Retrieve an ACL from the server */
911 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
912 struct inode *inode, const char *path,
913 u32 *pacllen)
915 struct cifs_ntsd *pntsd = NULL;
916 struct cifsFileInfo *open_file = NULL;
918 if (inode)
919 open_file = find_readable_file(CIFS_I(inode), true);
920 if (!open_file)
921 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
923 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
924 cifsFileInfo_put(open_file);
925 return pntsd;
928 /* Set an ACL on the server */
929 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
930 struct inode *inode, const char *path, int aclflag)
932 int oplock = 0;
933 unsigned int xid;
934 int rc, access_flags, create_options = 0;
935 __u16 fid;
936 struct cifs_tcon *tcon;
937 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
938 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
940 if (IS_ERR(tlink))
941 return PTR_ERR(tlink);
943 tcon = tlink_tcon(tlink);
944 xid = get_xid();
946 if (backup_cred(cifs_sb))
947 create_options |= CREATE_OPEN_BACKUP_INTENT;
949 if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
950 access_flags = WRITE_OWNER;
951 else
952 access_flags = WRITE_DAC;
954 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
955 create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
956 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
957 if (rc) {
958 cERROR(1, "Unable to open file to set ACL");
959 goto out;
962 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
963 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
965 CIFSSMBClose(xid, tcon, fid);
966 out:
967 free_xid(xid);
968 cifs_put_tlink(tlink);
969 return rc;
972 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
974 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
975 struct inode *inode, const char *path, const __u16 *pfid)
977 struct cifs_ntsd *pntsd = NULL;
978 u32 acllen = 0;
979 int rc = 0;
981 cFYI(DBG2, "converting ACL to mode for %s", path);
983 if (pfid)
984 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
985 else
986 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
988 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
989 if (IS_ERR(pntsd)) {
990 rc = PTR_ERR(pntsd);
991 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
992 } else {
993 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
994 kfree(pntsd);
995 if (rc)
996 cERROR(1, "parse sec desc failed rc = %d", rc);
999 return rc;
1002 /* Convert mode bits to an ACL so we can update the ACL on the server */
1004 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1005 uid_t uid, gid_t gid)
1007 int rc = 0;
1008 int aclflag = CIFS_ACL_DACL; /* default flag to set */
1009 __u32 secdesclen = 0;
1010 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1011 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1013 cFYI(DBG2, "set ACL from mode for %s", path);
1015 /* Get the security descriptor */
1016 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1017 if (IS_ERR(pntsd)) {
1018 rc = PTR_ERR(pntsd);
1019 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1020 goto out;
1024 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1025 * as chmod disables ACEs and set the security descriptor. Allocate
1026 * memory for the smb header, set security descriptor request security
1027 * descriptor parameters, and secuirty descriptor itself
1029 secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1030 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1031 if (!pnntsd) {
1032 cERROR(1, "Unable to allocate security descriptor");
1033 kfree(pntsd);
1034 return -ENOMEM;
1037 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1038 &aclflag);
1040 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1042 if (!rc) {
1043 /* Set the security descriptor */
1044 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1045 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1048 kfree(pnntsd);
1049 kfree(pntsd);
1050 out:
1051 return rc;