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