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