Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[~shefty/rdma-dev.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         uid_t fuid = cifs_sb->mnt_uid;
270         gid_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         if (sidkey->datalen != sizeof(uid_t)) {
301                 rc = -EIO;
302                 cFYI(1, "%s: Downcall contained malformed key "
303                         "(datalen=%hu)", __func__, sidkey->datalen);
304                 key_invalidate(sidkey);
305                 goto out_key_put;
306         }
307
308         if (sidtype == SIDOWNER)
309                 memcpy(&fuid, &sidkey->payload.value, sizeof(uid_t));
310         else
311                 memcpy(&fgid, &sidkey->payload.value, sizeof(gid_t));
312
313 out_key_put:
314         key_put(sidkey);
315 out_revert_creds:
316         revert_creds(saved_cred);
317         kfree(sidstr);
318
319         /*
320          * Note that we return 0 here unconditionally. If the mapping
321          * fails then we just fall back to using the mnt_uid/mnt_gid.
322          */
323         if (sidtype == SIDOWNER)
324                 fattr->cf_uid = fuid;
325         else
326                 fattr->cf_gid = fgid;
327         return 0;
328 }
329
330 int
331 init_cifs_idmap(void)
332 {
333         struct cred *cred;
334         struct key *keyring;
335         int ret;
336
337         cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
338
339         /* create an override credential set with a special thread keyring in
340          * which requests are cached
341          *
342          * this is used to prevent malicious redirections from being installed
343          * with add_key().
344          */
345         cred = prepare_kernel_cred(NULL);
346         if (!cred)
347                 return -ENOMEM;
348
349         keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
350                                 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
351                                 KEY_USR_VIEW | KEY_USR_READ,
352                                 KEY_ALLOC_NOT_IN_QUOTA, NULL);
353         if (IS_ERR(keyring)) {
354                 ret = PTR_ERR(keyring);
355                 goto failed_put_cred;
356         }
357
358         ret = register_key_type(&cifs_idmap_key_type);
359         if (ret < 0)
360                 goto failed_put_key;
361
362         /* instruct request_key() to use this special keyring as a cache for
363          * the results it looks up */
364         set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
365         cred->thread_keyring = keyring;
366         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
367         root_cred = cred;
368
369         cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
370         return 0;
371
372 failed_put_key:
373         key_put(keyring);
374 failed_put_cred:
375         put_cred(cred);
376         return ret;
377 }
378
379 void
380 exit_cifs_idmap(void)
381 {
382         key_revoke(root_cred->thread_keyring);
383         unregister_key_type(&cifs_idmap_key_type);
384         put_cred(root_cred);
385         cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
386 }
387
388 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
389 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
390                                 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
391 {
392         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
393         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
394
395         /* copy security descriptor control portion */
396         pnntsd->revision = pntsd->revision;
397         pnntsd->type = pntsd->type;
398         pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
399         pnntsd->sacloffset = 0;
400         pnntsd->osidoffset = cpu_to_le32(sidsoffset);
401         pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
402
403         /* copy owner sid */
404         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
405                                 le32_to_cpu(pntsd->osidoffset));
406         nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
407         cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
408
409         /* copy group sid */
410         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
411                                 le32_to_cpu(pntsd->gsidoffset));
412         ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
413                                         sizeof(struct cifs_sid));
414         cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
415
416         return;
417 }
418
419
420 /*
421    change posix mode to reflect permissions
422    pmode is the existing mode (we only want to overwrite part of this
423    bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
424 */
425 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
426                                  umode_t *pbits_to_set)
427 {
428         __u32 flags = le32_to_cpu(ace_flags);
429         /* the order of ACEs is important.  The canonical order is to begin with
430            DENY entries followed by ALLOW, otherwise an allow entry could be
431            encountered first, making the subsequent deny entry like "dead code"
432            which would be superflous since Windows stops when a match is made
433            for the operation you are trying to perform for your user */
434
435         /* For deny ACEs we change the mask so that subsequent allow access
436            control entries do not turn on the bits we are denying */
437         if (type == ACCESS_DENIED) {
438                 if (flags & GENERIC_ALL)
439                         *pbits_to_set &= ~S_IRWXUGO;
440
441                 if ((flags & GENERIC_WRITE) ||
442                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
443                         *pbits_to_set &= ~S_IWUGO;
444                 if ((flags & GENERIC_READ) ||
445                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
446                         *pbits_to_set &= ~S_IRUGO;
447                 if ((flags & GENERIC_EXECUTE) ||
448                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
449                         *pbits_to_set &= ~S_IXUGO;
450                 return;
451         } else if (type != ACCESS_ALLOWED) {
452                 cERROR(1, "unknown access control type %d", type);
453                 return;
454         }
455         /* else ACCESS_ALLOWED type */
456
457         if (flags & GENERIC_ALL) {
458                 *pmode |= (S_IRWXUGO & (*pbits_to_set));
459                 cFYI(DBG2, "all perms");
460                 return;
461         }
462         if ((flags & GENERIC_WRITE) ||
463                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
464                 *pmode |= (S_IWUGO & (*pbits_to_set));
465         if ((flags & GENERIC_READ) ||
466                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
467                 *pmode |= (S_IRUGO & (*pbits_to_set));
468         if ((flags & GENERIC_EXECUTE) ||
469                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
470                 *pmode |= (S_IXUGO & (*pbits_to_set));
471
472         cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
473         return;
474 }
475
476 /*
477    Generate access flags to reflect permissions mode is the existing mode.
478    This function is called for every ACE in the DACL whose SID matches
479    with either owner or group or everyone.
480 */
481
482 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
483                                 __u32 *pace_flags)
484 {
485         /* reset access mask */
486         *pace_flags = 0x0;
487
488         /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
489         mode &= bits_to_use;
490
491         /* check for R/W/X UGO since we do not know whose flags
492            is this but we have cleared all the bits sans RWX for
493            either user or group or other as per bits_to_use */
494         if (mode & S_IRUGO)
495                 *pace_flags |= SET_FILE_READ_RIGHTS;
496         if (mode & S_IWUGO)
497                 *pace_flags |= SET_FILE_WRITE_RIGHTS;
498         if (mode & S_IXUGO)
499                 *pace_flags |= SET_FILE_EXEC_RIGHTS;
500
501         cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
502         return;
503 }
504
505 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
506                         const struct cifs_sid *psid, __u64 nmode, umode_t bits)
507 {
508         int i;
509         __u16 size = 0;
510         __u32 access_req = 0;
511
512         pntace->type = ACCESS_ALLOWED;
513         pntace->flags = 0x0;
514         mode_to_access_flags(nmode, bits, &access_req);
515         if (!access_req)
516                 access_req = SET_MINIMUM_RIGHTS;
517         pntace->access_req = cpu_to_le32(access_req);
518
519         pntace->sid.revision = psid->revision;
520         pntace->sid.num_subauth = psid->num_subauth;
521         for (i = 0; i < NUM_AUTHS; i++)
522                 pntace->sid.authority[i] = psid->authority[i];
523         for (i = 0; i < psid->num_subauth; i++)
524                 pntace->sid.sub_auth[i] = psid->sub_auth[i];
525
526         size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
527         pntace->size = cpu_to_le16(size);
528
529         return size;
530 }
531
532
533 #ifdef CONFIG_CIFS_DEBUG2
534 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
535 {
536         int num_subauth;
537
538         /* validate that we do not go past end of acl */
539
540         if (le16_to_cpu(pace->size) < 16) {
541                 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
542                 return;
543         }
544
545         if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
546                 cERROR(1, "ACL too small to parse ACE");
547                 return;
548         }
549
550         num_subauth = pace->sid.num_subauth;
551         if (num_subauth) {
552                 int i;
553                 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
554                         pace->sid.revision, pace->sid.num_subauth, pace->type,
555                         pace->flags, le16_to_cpu(pace->size));
556                 for (i = 0; i < num_subauth; ++i) {
557                         cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
558                                 le32_to_cpu(pace->sid.sub_auth[i]));
559                 }
560
561                 /* BB add length check to make sure that we do not have huge
562                         num auths and therefore go off the end */
563         }
564
565         return;
566 }
567 #endif
568
569
570 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
571                        struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
572                        struct cifs_fattr *fattr)
573 {
574         int i;
575         int num_aces = 0;
576         int acl_size;
577         char *acl_base;
578         struct cifs_ace **ppace;
579
580         /* BB need to add parm so we can store the SID BB */
581
582         if (!pdacl) {
583                 /* no DACL in the security descriptor, set
584                    all the permissions for user/group/other */
585                 fattr->cf_mode |= S_IRWXUGO;
586                 return;
587         }
588
589         /* validate that we do not go past end of acl */
590         if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
591                 cERROR(1, "ACL too small to parse DACL");
592                 return;
593         }
594
595         cFYI(DBG2, "DACL revision %d size %d num aces %d",
596                 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
597                 le32_to_cpu(pdacl->num_aces));
598
599         /* reset rwx permissions for user/group/other.
600            Also, if num_aces is 0 i.e. DACL has no ACEs,
601            user/group/other have no permissions */
602         fattr->cf_mode &= ~(S_IRWXUGO);
603
604         acl_base = (char *)pdacl;
605         acl_size = sizeof(struct cifs_acl);
606
607         num_aces = le32_to_cpu(pdacl->num_aces);
608         if (num_aces > 0) {
609                 umode_t user_mask = S_IRWXU;
610                 umode_t group_mask = S_IRWXG;
611                 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
612
613                 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
614                         return;
615                 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
616                                 GFP_KERNEL);
617                 if (!ppace) {
618                         cERROR(1, "DACL memory allocation error");
619                         return;
620                 }
621
622                 for (i = 0; i < num_aces; ++i) {
623                         ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
624 #ifdef CONFIG_CIFS_DEBUG2
625                         dump_ace(ppace[i], end_of_acl);
626 #endif
627                         if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
628                                 access_flags_to_mode(ppace[i]->access_req,
629                                                      ppace[i]->type,
630                                                      &fattr->cf_mode,
631                                                      &user_mask);
632                         if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
633                                 access_flags_to_mode(ppace[i]->access_req,
634                                                      ppace[i]->type,
635                                                      &fattr->cf_mode,
636                                                      &group_mask);
637                         if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
638                                 access_flags_to_mode(ppace[i]->access_req,
639                                                      ppace[i]->type,
640                                                      &fattr->cf_mode,
641                                                      &other_mask);
642                         if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
643                                 access_flags_to_mode(ppace[i]->access_req,
644                                                      ppace[i]->type,
645                                                      &fattr->cf_mode,
646                                                      &other_mask);
647
648
649 /*                      memcpy((void *)(&(cifscred->aces[i])),
650                                 (void *)ppace[i],
651                                 sizeof(struct cifs_ace)); */
652
653                         acl_base = (char *)ppace[i];
654                         acl_size = le16_to_cpu(ppace[i]->size);
655                 }
656
657                 kfree(ppace);
658         }
659
660         return;
661 }
662
663
664 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
665                         struct cifs_sid *pgrpsid, __u64 nmode)
666 {
667         u16 size = 0;
668         struct cifs_acl *pnndacl;
669
670         pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
671
672         size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
673                                         pownersid, nmode, S_IRWXU);
674         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
675                                         pgrpsid, nmode, S_IRWXG);
676         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
677                                          &sid_everyone, nmode, S_IRWXO);
678
679         pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
680         pndacl->num_aces = cpu_to_le32(3);
681
682         return 0;
683 }
684
685
686 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
687 {
688         /* BB need to add parm so we can store the SID BB */
689
690         /* validate that we do not go past end of ACL - sid must be at least 8
691            bytes long (assuming no sub-auths - e.g. the null SID */
692         if (end_of_acl < (char *)psid + 8) {
693                 cERROR(1, "ACL too small to parse SID %p", psid);
694                 return -EINVAL;
695         }
696
697 #ifdef CONFIG_CIFS_DEBUG2
698         if (psid->num_subauth) {
699                 int i;
700                 cFYI(1, "SID revision %d num_auth %d",
701                         psid->revision, psid->num_subauth);
702
703                 for (i = 0; i < psid->num_subauth; i++) {
704                         cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
705                                 le32_to_cpu(psid->sub_auth[i]));
706                 }
707
708                 /* BB add length check to make sure that we do not have huge
709                         num auths and therefore go off the end */
710                 cFYI(1, "RID 0x%x",
711                         le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
712         }
713 #endif
714
715         return 0;
716 }
717
718
719 /* Convert CIFS ACL to POSIX form */
720 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
721                 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
722 {
723         int rc = 0;
724         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
725         struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
726         char *end_of_acl = ((char *)pntsd) + acl_len;
727         __u32 dacloffset;
728
729         if (pntsd == NULL)
730                 return -EIO;
731
732         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
733                                 le32_to_cpu(pntsd->osidoffset));
734         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
735                                 le32_to_cpu(pntsd->gsidoffset));
736         dacloffset = le32_to_cpu(pntsd->dacloffset);
737         dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
738         cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
739                  "sacloffset 0x%x dacloffset 0x%x",
740                  pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
741                  le32_to_cpu(pntsd->gsidoffset),
742                  le32_to_cpu(pntsd->sacloffset), dacloffset);
743 /*      cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
744         rc = parse_sid(owner_sid_ptr, end_of_acl);
745         if (rc) {
746                 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
747                 return rc;
748         }
749         rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
750         if (rc) {
751                 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
752                 return rc;
753         }
754
755         rc = parse_sid(group_sid_ptr, end_of_acl);
756         if (rc) {
757                 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
758                 return rc;
759         }
760         rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
761         if (rc) {
762                 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
763                 return rc;
764         }
765
766         if (dacloffset)
767                 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
768                            group_sid_ptr, fattr);
769         else
770                 cFYI(1, "no ACL"); /* BB grant all or default perms? */
771
772         return rc;
773 }
774
775 /* Convert permission bits from mode to equivalent CIFS ACL */
776 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
777         __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
778 {
779         int rc = 0;
780         __u32 dacloffset;
781         __u32 ndacloffset;
782         __u32 sidsoffset;
783         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
784         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
785         struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
786         struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
787
788         if (nmode != NO_CHANGE_64) { /* chmod */
789                 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
790                                 le32_to_cpu(pntsd->osidoffset));
791                 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
792                                 le32_to_cpu(pntsd->gsidoffset));
793                 dacloffset = le32_to_cpu(pntsd->dacloffset);
794                 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
795                 ndacloffset = sizeof(struct cifs_ntsd);
796                 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
797                 ndacl_ptr->revision = dacl_ptr->revision;
798                 ndacl_ptr->size = 0;
799                 ndacl_ptr->num_aces = 0;
800
801                 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
802                                         nmode);
803                 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
804                 /* copy sec desc control portion & owner and group sids */
805                 copy_sec_desc(pntsd, pnntsd, sidsoffset);
806                 *aclflag = CIFS_ACL_DACL;
807         } else {
808                 memcpy(pnntsd, pntsd, secdesclen);
809                 if (uid != NO_CHANGE_32) { /* chown */
810                         owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
811                                         le32_to_cpu(pnntsd->osidoffset));
812                         nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
813                                                                 GFP_KERNEL);
814                         if (!nowner_sid_ptr)
815                                 return -ENOMEM;
816                         rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
817                         if (rc) {
818                                 cFYI(1, "%s: Mapping error %d for owner id %d",
819                                                 __func__, rc, uid);
820                                 kfree(nowner_sid_ptr);
821                                 return rc;
822                         }
823                         cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
824                         kfree(nowner_sid_ptr);
825                         *aclflag = CIFS_ACL_OWNER;
826                 }
827                 if (gid != NO_CHANGE_32) { /* chgrp */
828                         group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
829                                         le32_to_cpu(pnntsd->gsidoffset));
830                         ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
831                                                                 GFP_KERNEL);
832                         if (!ngroup_sid_ptr)
833                                 return -ENOMEM;
834                         rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
835                         if (rc) {
836                                 cFYI(1, "%s: Mapping error %d for group id %d",
837                                                 __func__, rc, gid);
838                                 kfree(ngroup_sid_ptr);
839                                 return rc;
840                         }
841                         cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
842                         kfree(ngroup_sid_ptr);
843                         *aclflag = CIFS_ACL_GROUP;
844                 }
845         }
846
847         return rc;
848 }
849
850 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
851                 __u16 fid, u32 *pacllen)
852 {
853         struct cifs_ntsd *pntsd = NULL;
854         unsigned int xid;
855         int rc;
856         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
857
858         if (IS_ERR(tlink))
859                 return ERR_CAST(tlink);
860
861         xid = get_xid();
862         rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
863         free_xid(xid);
864
865         cifs_put_tlink(tlink);
866
867         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
868         if (rc)
869                 return ERR_PTR(rc);
870         return pntsd;
871 }
872
873 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
874                 const char *path, u32 *pacllen)
875 {
876         struct cifs_ntsd *pntsd = NULL;
877         int oplock = 0;
878         unsigned int xid;
879         int rc, create_options = 0;
880         __u16 fid;
881         struct cifs_tcon *tcon;
882         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
883
884         if (IS_ERR(tlink))
885                 return ERR_CAST(tlink);
886
887         tcon = tlink_tcon(tlink);
888         xid = get_xid();
889
890         if (backup_cred(cifs_sb))
891                 create_options |= CREATE_OPEN_BACKUP_INTENT;
892
893         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
894                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
895                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
896         if (!rc) {
897                 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
898                 CIFSSMBClose(xid, tcon, fid);
899         }
900
901         cifs_put_tlink(tlink);
902         free_xid(xid);
903
904         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
905         if (rc)
906                 return ERR_PTR(rc);
907         return pntsd;
908 }
909
910 /* Retrieve an ACL from the server */
911 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
912                                       struct inode *inode, const char *path,
913                                       u32 *pacllen)
914 {
915         struct cifs_ntsd *pntsd = NULL;
916         struct cifsFileInfo *open_file = NULL;
917
918         if (inode)
919                 open_file = find_readable_file(CIFS_I(inode), true);
920         if (!open_file)
921                 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
922
923         pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
924         cifsFileInfo_put(open_file);
925         return pntsd;
926 }
927
928  /* Set an ACL on the server */
929 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
930                         struct inode *inode, const char *path, int aclflag)
931 {
932         int oplock = 0;
933         unsigned int xid;
934         int rc, access_flags, create_options = 0;
935         __u16 fid;
936         struct cifs_tcon *tcon;
937         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
938         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
939
940         if (IS_ERR(tlink))
941                 return PTR_ERR(tlink);
942
943         tcon = tlink_tcon(tlink);
944         xid = get_xid();
945
946         if (backup_cred(cifs_sb))
947                 create_options |= CREATE_OPEN_BACKUP_INTENT;
948
949         if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
950                 access_flags = WRITE_OWNER;
951         else
952                 access_flags = WRITE_DAC;
953
954         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
955                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
956                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
957         if (rc) {
958                 cERROR(1, "Unable to open file to set ACL");
959                 goto out;
960         }
961
962         rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
963         cFYI(DBG2, "SetCIFSACL rc = %d", rc);
964
965         CIFSSMBClose(xid, tcon, fid);
966 out:
967         free_xid(xid);
968         cifs_put_tlink(tlink);
969         return rc;
970 }
971
972 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
973 int
974 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
975                   struct inode *inode, const char *path, const __u16 *pfid)
976 {
977         struct cifs_ntsd *pntsd = NULL;
978         u32 acllen = 0;
979         int rc = 0;
980
981         cFYI(DBG2, "converting ACL to mode for %s", path);
982
983         if (pfid)
984                 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
985         else
986                 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
987
988         /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
989         if (IS_ERR(pntsd)) {
990                 rc = PTR_ERR(pntsd);
991                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
992         } else {
993                 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
994                 kfree(pntsd);
995                 if (rc)
996                         cERROR(1, "parse sec desc failed rc = %d", rc);
997         }
998
999         return rc;
1000 }
1001
1002 /* Convert mode bits to an ACL so we can update the ACL on the server */
1003 int
1004 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1005                         uid_t uid, gid_t gid)
1006 {
1007         int rc = 0;
1008         int aclflag = CIFS_ACL_DACL; /* default flag to set */
1009         __u32 secdesclen = 0;
1010         struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1011         struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1012
1013         cFYI(DBG2, "set ACL from mode for %s", path);
1014
1015         /* Get the security descriptor */
1016         pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1017         if (IS_ERR(pntsd)) {
1018                 rc = PTR_ERR(pntsd);
1019                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1020                 goto out;
1021         }
1022
1023         /*
1024          * Add three ACEs for owner, group, everyone getting rid of other ACEs
1025          * as chmod disables ACEs and set the security descriptor. Allocate
1026          * memory for the smb header, set security descriptor request security
1027          * descriptor parameters, and secuirty descriptor itself
1028          */
1029         secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1030         pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1031         if (!pnntsd) {
1032                 cERROR(1, "Unable to allocate security descriptor");
1033                 kfree(pntsd);
1034                 return -ENOMEM;
1035         }
1036
1037         rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1038                                 &aclflag);
1039
1040         cFYI(DBG2, "build_sec_desc rc: %d", rc);
1041
1042         if (!rc) {
1043                 /* Set the security descriptor */
1044                 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1045                 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1046         }
1047
1048         kfree(pnntsd);
1049         kfree(pntsd);
1050 out:
1051         return rc;
1052 }