71e8a56e9479567e9f5ad0fb201a2ea3e91d6e99
[cascardo/linux.git] / fs / cifs / cifsacl.c
1 /*
2  *   fs/cifs/cifsacl.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2007,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for mapping CIFS/NTFS ACLs
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24 #include <linux/fs.h>
25 #include <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/keyctl.h>
28 #include <linux/key-type.h>
29 #include <keys/user-type.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsacl.h"
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
35
36 /* security id for everyone/world system group */
37 static const struct cifs_sid sid_everyone = {
38         1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39 /* security id for Authenticated Users system group */
40 static const struct cifs_sid sid_authusers = {
41         1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
42 /* group users */
43 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44
45 static const struct cred *root_cred;
46
47 static int
48 cifs_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
74 static inline void
75 cifs_idmap_key_destroy(struct key *key)
76 {
77         if (key->datalen > sizeof(key->payload))
78                 kfree(key->payload.data[0]);
79 }
80
81 static 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
88 static char *
89 sid_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  */
140 static int
141 compare_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
186 static void
187 cifs_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
199 static int
200 id_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);
247 out_key_put:
248         key_put(sidkey);
249 out_revert_creds:
250         revert_creds(saved_cred);
251         return rc;
252
253 invalidate_key:
254         key_invalidate(sidkey);
255         goto out_key_put;
256 }
257
258 static int
259 sid_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
322 out_key_put:
323         key_put(sidkey);
324 out_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
339 int
340 init_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, 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
383 failed_put_key:
384         key_put(keyring);
385 failed_put_cred:
386         put_cred(cred);
387         return ret;
388 }
389
390 void
391 exit_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 */
400 static 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 */
436 static 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
493 static 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
517 static __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
546 static 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
582 static 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
674 static 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
696 static 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 */
730 static 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 */
788 static 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
866 struct 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
890 static 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 */
936 struct 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 */
954 int 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);
999 out:
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 */
1006 int
1007 cifs_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 */
1050 int
1051 id_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 }