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