]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - fs/cifs/cifsacl.c
a4aa0f0af5c3f157350ac71e744cfd55f02e25fe
[linux-2.6.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
37 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
38         {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
39         {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
40         {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
41         {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
42         {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"},
43         {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"},
44         {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} }
45 ;
46
47
48 /* security id for everyone/world system group */
49 static const struct cifs_sid sid_everyone = {
50         1, 1, {0, 0, 0, 0, 0, 1}, {0} };
51 /* security id for Authenticated Users system group */
52 static const struct cifs_sid sid_authusers = {
53         1, 1, {0, 0, 0, 0, 0, 5}, {11} };
54 /* group users */
55 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
56
57 const struct cred *root_cred;
58
59 static void
60 shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
61                         int *nr_del)
62 {
63         struct rb_node *node;
64         struct rb_node *tmp;
65         struct cifs_sid_id *psidid;
66
67         node = rb_first(root);
68         while (node) {
69                 tmp = node;
70                 node = rb_next(tmp);
71                 psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
72                 if (nr_to_scan == 0 || *nr_del == nr_to_scan)
73                         ++(*nr_rem);
74                 else {
75                         if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
76                                                 && psidid->refcount == 0) {
77                                 rb_erase(tmp, root);
78                                 ++(*nr_del);
79                         } else
80                                 ++(*nr_rem);
81                 }
82         }
83 }
84
85 /*
86  * Run idmap cache shrinker.
87  */
88 static int
89 cifs_idmap_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
90 {
91         int nr_del = 0;
92         int nr_rem = 0;
93         struct rb_root *root;
94
95         root = &uidtree;
96         spin_lock(&siduidlock);
97         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
98         spin_unlock(&siduidlock);
99
100         root = &gidtree;
101         spin_lock(&sidgidlock);
102         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
103         spin_unlock(&sidgidlock);
104
105         return nr_rem;
106 }
107
108 static struct shrinker cifs_shrinker = {
109         .shrink = cifs_idmap_shrinker,
110         .seeks = DEFAULT_SEEKS,
111 };
112
113 static int
114 cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
115 {
116         char *payload;
117
118         payload = kmalloc(datalen, GFP_KERNEL);
119         if (!payload)
120                 return -ENOMEM;
121
122         memcpy(payload, data, datalen);
123         key->payload.data = payload;
124         return 0;
125 }
126
127 static inline void
128 cifs_idmap_key_destroy(struct key *key)
129 {
130         kfree(key->payload.data);
131 }
132
133 struct key_type cifs_idmap_key_type = {
134         .name        = "cifs.cifs_idmap",
135         .instantiate = cifs_idmap_key_instantiate,
136         .destroy     = cifs_idmap_key_destroy,
137         .describe    = user_describe,
138         .match       = user_match,
139 };
140
141 static void
142 sid_to_str(struct cifs_sid *sidptr, char *sidstr)
143 {
144         int i;
145         unsigned long saval;
146         char *strptr;
147
148         strptr = sidstr;
149
150         sprintf(strptr, "%s", "S");
151         strptr = sidstr + strlen(sidstr);
152
153         sprintf(strptr, "-%d", sidptr->revision);
154         strptr = sidstr + strlen(sidstr);
155
156         for (i = 0; i < 6; ++i) {
157                 if (sidptr->authority[i]) {
158                         sprintf(strptr, "-%d", sidptr->authority[i]);
159                         strptr = sidstr + strlen(sidstr);
160                 }
161         }
162
163         for (i = 0; i < sidptr->num_subauth; ++i) {
164                 saval = le32_to_cpu(sidptr->sub_auth[i]);
165                 sprintf(strptr, "-%ld", saval);
166                 strptr = sidstr + strlen(sidstr);
167         }
168 }
169
170 static void
171 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
172                 struct cifs_sid_id **psidid, char *typestr)
173 {
174         int rc;
175         char *strptr;
176         struct rb_node *node = root->rb_node;
177         struct rb_node *parent = NULL;
178         struct rb_node **linkto = &(root->rb_node);
179         struct cifs_sid_id *lsidid;
180
181         while (node) {
182                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
183                 parent = node;
184                 rc = compare_sids(sidptr, &((lsidid)->sid));
185                 if (rc > 0) {
186                         linkto = &(node->rb_left);
187                         node = node->rb_left;
188                 } else if (rc < 0) {
189                         linkto = &(node->rb_right);
190                         node = node->rb_right;
191                 }
192         }
193
194         memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
195         (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
196         (*psidid)->refcount = 0;
197
198         sprintf((*psidid)->sidstr, "%s", typestr);
199         strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
200         sid_to_str(&(*psidid)->sid, strptr);
201
202         clear_bit(SID_ID_PENDING, &(*psidid)->state);
203         clear_bit(SID_ID_MAPPED, &(*psidid)->state);
204
205         rb_link_node(&(*psidid)->rbnode, parent, linkto);
206         rb_insert_color(&(*psidid)->rbnode, root);
207 }
208
209 static struct cifs_sid_id *
210 id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
211 {
212         int rc;
213         struct rb_node *node = root->rb_node;
214         struct rb_node *parent = NULL;
215         struct rb_node **linkto = &(root->rb_node);
216         struct cifs_sid_id *lsidid;
217
218         while (node) {
219                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
220                 parent = node;
221                 rc = compare_sids(sidptr, &((lsidid)->sid));
222                 if (rc > 0) {
223                         linkto = &(node->rb_left);
224                         node = node->rb_left;
225                 } else if (rc < 0) {
226                         linkto = &(node->rb_right);
227                         node = node->rb_right;
228                 } else /* node found */
229                         return lsidid;
230         }
231
232         return NULL;
233 }
234
235 static int
236 sidid_pending_wait(void *unused)
237 {
238         schedule();
239         return signal_pending(current) ? -ERESTARTSYS : 0;
240 }
241
242 static int
243 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
244                 struct cifs_fattr *fattr, uint sidtype)
245 {
246         int rc;
247         unsigned long cid;
248         struct key *idkey;
249         const struct cred *saved_cred;
250         struct cifs_sid_id *psidid, *npsidid;
251         struct rb_root *cidtree;
252         spinlock_t *cidlock;
253
254         if (sidtype == SIDOWNER) {
255                 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
256                 cidlock = &siduidlock;
257                 cidtree = &uidtree;
258         } else if (sidtype == SIDGROUP) {
259                 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
260                 cidlock = &sidgidlock;
261                 cidtree = &gidtree;
262         } else
263                 return -ENOENT;
264
265         spin_lock(cidlock);
266         psidid = id_rb_search(cidtree, psid);
267
268         if (!psidid) { /* node does not exist, allocate one & attempt adding */
269                 spin_unlock(cidlock);
270                 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
271                 if (!npsidid)
272                         return -ENOMEM;
273
274                 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
275                 if (!npsidid->sidstr) {
276                         kfree(npsidid);
277                         return -ENOMEM;
278                 }
279
280                 spin_lock(cidlock);
281                 psidid = id_rb_search(cidtree, psid);
282                 if (psidid) { /* node happened to get inserted meanwhile */
283                         ++psidid->refcount;
284                         spin_unlock(cidlock);
285                         kfree(npsidid->sidstr);
286                         kfree(npsidid);
287                 } else {
288                         psidid = npsidid;
289                         id_rb_insert(cidtree, psid, &psidid,
290                                         sidtype == SIDOWNER ? "os:" : "gs:");
291                         ++psidid->refcount;
292                         spin_unlock(cidlock);
293                 }
294         } else {
295                 ++psidid->refcount;
296                 spin_unlock(cidlock);
297         }
298
299         /*
300          * If we are here, it is safe to access psidid and its fields
301          * since a reference was taken earlier while holding the spinlock.
302          * A reference on the node is put without holding the spinlock
303          * and it is OK to do so in this case, shrinker will not erase
304          * this node until all references are put and we do not access
305          * any fields of the node after a reference is put .
306          */
307         if (test_bit(SID_ID_MAPPED, &psidid->state)) {
308                 cid = psidid->id;
309                 psidid->time = jiffies; /* update ts for accessing */
310                 goto sid_to_id_out;
311         }
312
313         if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
314                 goto sid_to_id_out;
315
316         if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
317                 saved_cred = override_creds(root_cred);
318                 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
319                 if (IS_ERR(idkey))
320                         cFYI(1, "%s: Can't map SID to an id", __func__);
321                 else {
322                         cid = *(unsigned long *)idkey->payload.value;
323                         psidid->id = cid;
324                         set_bit(SID_ID_MAPPED, &psidid->state);
325                         key_put(idkey);
326                         kfree(psidid->sidstr);
327                 }
328                 revert_creds(saved_cred);
329                 psidid->time = jiffies; /* update ts for accessing */
330                 clear_bit(SID_ID_PENDING, &psidid->state);
331                 wake_up_bit(&psidid->state, SID_ID_PENDING);
332         } else {
333                 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
334                                 sidid_pending_wait, TASK_INTERRUPTIBLE);
335                 if (rc) {
336                         cFYI(1, "%s: sidid_pending_wait interrupted %d",
337                                         __func__, rc);
338                         --psidid->refcount; /* decremented without spinlock */
339                         return rc;
340                 }
341                 if (test_bit(SID_ID_MAPPED, &psidid->state))
342                         cid = psidid->id;
343         }
344
345 sid_to_id_out:
346         --psidid->refcount; /* decremented without spinlock */
347         if (sidtype == SIDOWNER)
348                 fattr->cf_uid = cid;
349         else
350                 fattr->cf_gid = cid;
351
352         return 0;
353 }
354
355 int
356 init_cifs_idmap(void)
357 {
358         struct cred *cred;
359         struct key *keyring;
360         int ret;
361
362         cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
363
364         /* create an override credential set with a special thread keyring in
365          * which requests are cached
366          *
367          * this is used to prevent malicious redirections from being installed
368          * with add_key().
369          */
370         cred = prepare_kernel_cred(NULL);
371         if (!cred)
372                 return -ENOMEM;
373
374         keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
375                             (KEY_POS_ALL & ~KEY_POS_SETATTR) |
376                             KEY_USR_VIEW | KEY_USR_READ,
377                             KEY_ALLOC_NOT_IN_QUOTA);
378         if (IS_ERR(keyring)) {
379                 ret = PTR_ERR(keyring);
380                 goto failed_put_cred;
381         }
382
383         ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
384         if (ret < 0)
385                 goto failed_put_key;
386
387         ret = register_key_type(&cifs_idmap_key_type);
388         if (ret < 0)
389                 goto failed_put_key;
390
391         /* instruct request_key() to use this special keyring as a cache for
392          * the results it looks up */
393         cred->thread_keyring = keyring;
394         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
395         root_cred = cred;
396
397         spin_lock_init(&siduidlock);
398         uidtree = RB_ROOT;
399         spin_lock_init(&sidgidlock);
400         gidtree = RB_ROOT;
401
402         register_shrinker(&cifs_shrinker);
403
404         cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
405         return 0;
406
407 failed_put_key:
408         key_put(keyring);
409 failed_put_cred:
410         put_cred(cred);
411         return ret;
412 }
413
414 void
415 exit_cifs_idmap(void)
416 {
417         key_revoke(root_cred->thread_keyring);
418         unregister_key_type(&cifs_idmap_key_type);
419         put_cred(root_cred);
420         unregister_shrinker(&cifs_shrinker);
421         cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
422 }
423
424 void
425 cifs_destroy_idmaptrees(void)
426 {
427         struct rb_root *root;
428         struct rb_node *node;
429
430         root = &uidtree;
431         spin_lock(&siduidlock);
432         while ((node = rb_first(root)))
433                 rb_erase(node, root);
434         spin_unlock(&siduidlock);
435
436         root = &gidtree;
437         spin_lock(&sidgidlock);
438         while ((node = rb_first(root)))
439                 rb_erase(node, root);
440         spin_unlock(&sidgidlock);
441 }
442
443 int match_sid(struct cifs_sid *ctsid)
444 {
445         int i, j;
446         int num_subauth, num_sat, num_saw;
447         struct cifs_sid *cwsid;
448
449         if (!ctsid)
450                 return -1;
451
452         for (i = 0; i < NUM_WK_SIDS; ++i) {
453                 cwsid = &(wksidarr[i].cifssid);
454
455                 /* compare the revision */
456                 if (ctsid->revision != cwsid->revision)
457                         continue;
458
459                 /* compare all of the six auth values */
460                 for (j = 0; j < 6; ++j) {
461                         if (ctsid->authority[j] != cwsid->authority[j])
462                                 break;
463                 }
464                 if (j < 6)
465                         continue; /* all of the auth values did not match */
466
467                 /* compare all of the subauth values if any */
468                 num_sat = ctsid->num_subauth;
469                 num_saw = cwsid->num_subauth;
470                 num_subauth = num_sat < num_saw ? num_sat : num_saw;
471                 if (num_subauth) {
472                         for (j = 0; j < num_subauth; ++j) {
473                                 if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
474                                         break;
475                         }
476                         if (j < num_subauth)
477                                 continue; /* all sub_auth values do not match */
478                 }
479
480                 cFYI(1, "matching sid: %s\n", wksidarr[i].sidname);
481                 return 0; /* sids compare/match */
482         }
483
484         cFYI(1, "No matching sid");
485         return -1;
486 }
487
488 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
489    the same returns 1, if they do not match returns 0 */
490 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
491 {
492         int i;
493         int num_subauth, num_sat, num_saw;
494
495         if ((!ctsid) || (!cwsid))
496                 return 1;
497
498         /* compare the revision */
499         if (ctsid->revision != cwsid->revision) {
500                 if (ctsid->revision > cwsid->revision)
501                         return 1;
502                 else
503                         return -1;
504         }
505
506         /* compare all of the six auth values */
507         for (i = 0; i < 6; ++i) {
508                 if (ctsid->authority[i] != cwsid->authority[i]) {
509                         if (ctsid->authority[i] > cwsid->authority[i])
510                                 return 1;
511                         else
512                                 return -1;
513                 }
514         }
515
516         /* compare all of the subauth values if any */
517         num_sat = ctsid->num_subauth;
518         num_saw = cwsid->num_subauth;
519         num_subauth = num_sat < num_saw ? num_sat : num_saw;
520         if (num_subauth) {
521                 for (i = 0; i < num_subauth; ++i) {
522                         if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
523                                 if (ctsid->sub_auth[i] > cwsid->sub_auth[i])
524                                         return 1;
525                                 else
526                                         return -1;
527                         }
528                 }
529         }
530
531         return 0; /* sids compare/match */
532 }
533
534
535 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
536 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
537                                 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
538 {
539         int i;
540
541         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
542         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
543
544         /* copy security descriptor control portion */
545         pnntsd->revision = pntsd->revision;
546         pnntsd->type = pntsd->type;
547         pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
548         pnntsd->sacloffset = 0;
549         pnntsd->osidoffset = cpu_to_le32(sidsoffset);
550         pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
551
552         /* copy owner sid */
553         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
554                                 le32_to_cpu(pntsd->osidoffset));
555         nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
556
557         nowner_sid_ptr->revision = owner_sid_ptr->revision;
558         nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
559         for (i = 0; i < 6; i++)
560                 nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
561         for (i = 0; i < 5; i++)
562                 nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
563
564         /* copy group sid */
565         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
566                                 le32_to_cpu(pntsd->gsidoffset));
567         ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
568                                         sizeof(struct cifs_sid));
569
570         ngroup_sid_ptr->revision = group_sid_ptr->revision;
571         ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
572         for (i = 0; i < 6; i++)
573                 ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
574         for (i = 0; i < 5; i++)
575                 ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
576
577         return;
578 }
579
580
581 /*
582    change posix mode to reflect permissions
583    pmode is the existing mode (we only want to overwrite part of this
584    bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
585 */
586 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
587                                  umode_t *pbits_to_set)
588 {
589         __u32 flags = le32_to_cpu(ace_flags);
590         /* the order of ACEs is important.  The canonical order is to begin with
591            DENY entries followed by ALLOW, otherwise an allow entry could be
592            encountered first, making the subsequent deny entry like "dead code"
593            which would be superflous since Windows stops when a match is made
594            for the operation you are trying to perform for your user */
595
596         /* For deny ACEs we change the mask so that subsequent allow access
597            control entries do not turn on the bits we are denying */
598         if (type == ACCESS_DENIED) {
599                 if (flags & GENERIC_ALL)
600                         *pbits_to_set &= ~S_IRWXUGO;
601
602                 if ((flags & GENERIC_WRITE) ||
603                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
604                         *pbits_to_set &= ~S_IWUGO;
605                 if ((flags & GENERIC_READ) ||
606                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
607                         *pbits_to_set &= ~S_IRUGO;
608                 if ((flags & GENERIC_EXECUTE) ||
609                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
610                         *pbits_to_set &= ~S_IXUGO;
611                 return;
612         } else if (type != ACCESS_ALLOWED) {
613                 cERROR(1, "unknown access control type %d", type);
614                 return;
615         }
616         /* else ACCESS_ALLOWED type */
617
618         if (flags & GENERIC_ALL) {
619                 *pmode |= (S_IRWXUGO & (*pbits_to_set));
620                 cFYI(DBG2, "all perms");
621                 return;
622         }
623         if ((flags & GENERIC_WRITE) ||
624                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
625                 *pmode |= (S_IWUGO & (*pbits_to_set));
626         if ((flags & GENERIC_READ) ||
627                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
628                 *pmode |= (S_IRUGO & (*pbits_to_set));
629         if ((flags & GENERIC_EXECUTE) ||
630                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
631                 *pmode |= (S_IXUGO & (*pbits_to_set));
632
633         cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
634         return;
635 }
636
637 /*
638    Generate access flags to reflect permissions mode is the existing mode.
639    This function is called for every ACE in the DACL whose SID matches
640    with either owner or group or everyone.
641 */
642
643 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
644                                 __u32 *pace_flags)
645 {
646         /* reset access mask */
647         *pace_flags = 0x0;
648
649         /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
650         mode &= bits_to_use;
651
652         /* check for R/W/X UGO since we do not know whose flags
653            is this but we have cleared all the bits sans RWX for
654            either user or group or other as per bits_to_use */
655         if (mode & S_IRUGO)
656                 *pace_flags |= SET_FILE_READ_RIGHTS;
657         if (mode & S_IWUGO)
658                 *pace_flags |= SET_FILE_WRITE_RIGHTS;
659         if (mode & S_IXUGO)
660                 *pace_flags |= SET_FILE_EXEC_RIGHTS;
661
662         cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
663         return;
664 }
665
666 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
667                         const struct cifs_sid *psid, __u64 nmode, umode_t bits)
668 {
669         int i;
670         __u16 size = 0;
671         __u32 access_req = 0;
672
673         pntace->type = ACCESS_ALLOWED;
674         pntace->flags = 0x0;
675         mode_to_access_flags(nmode, bits, &access_req);
676         if (!access_req)
677                 access_req = SET_MINIMUM_RIGHTS;
678         pntace->access_req = cpu_to_le32(access_req);
679
680         pntace->sid.revision = psid->revision;
681         pntace->sid.num_subauth = psid->num_subauth;
682         for (i = 0; i < 6; i++)
683                 pntace->sid.authority[i] = psid->authority[i];
684         for (i = 0; i < psid->num_subauth; i++)
685                 pntace->sid.sub_auth[i] = psid->sub_auth[i];
686
687         size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
688         pntace->size = cpu_to_le16(size);
689
690         return size;
691 }
692
693
694 #ifdef CONFIG_CIFS_DEBUG2
695 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
696 {
697         int num_subauth;
698
699         /* validate that we do not go past end of acl */
700
701         if (le16_to_cpu(pace->size) < 16) {
702                 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
703                 return;
704         }
705
706         if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
707                 cERROR(1, "ACL too small to parse ACE");
708                 return;
709         }
710
711         num_subauth = pace->sid.num_subauth;
712         if (num_subauth) {
713                 int i;
714                 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
715                         pace->sid.revision, pace->sid.num_subauth, pace->type,
716                         pace->flags, le16_to_cpu(pace->size));
717                 for (i = 0; i < num_subauth; ++i) {
718                         cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
719                                 le32_to_cpu(pace->sid.sub_auth[i]));
720                 }
721
722                 /* BB add length check to make sure that we do not have huge
723                         num auths and therefore go off the end */
724         }
725
726         return;
727 }
728 #endif
729
730
731 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
732                        struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
733                        struct cifs_fattr *fattr)
734 {
735         int i;
736         int num_aces = 0;
737         int acl_size;
738         char *acl_base;
739         struct cifs_ace **ppace;
740
741         /* BB need to add parm so we can store the SID BB */
742
743         if (!pdacl) {
744                 /* no DACL in the security descriptor, set
745                    all the permissions for user/group/other */
746                 fattr->cf_mode |= S_IRWXUGO;
747                 return;
748         }
749
750         /* validate that we do not go past end of acl */
751         if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
752                 cERROR(1, "ACL too small to parse DACL");
753                 return;
754         }
755
756         cFYI(DBG2, "DACL revision %d size %d num aces %d",
757                 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
758                 le32_to_cpu(pdacl->num_aces));
759
760         /* reset rwx permissions for user/group/other.
761            Also, if num_aces is 0 i.e. DACL has no ACEs,
762            user/group/other have no permissions */
763         fattr->cf_mode &= ~(S_IRWXUGO);
764
765         acl_base = (char *)pdacl;
766         acl_size = sizeof(struct cifs_acl);
767
768         num_aces = le32_to_cpu(pdacl->num_aces);
769         if (num_aces  > 0) {
770                 umode_t user_mask = S_IRWXU;
771                 umode_t group_mask = S_IRWXG;
772                 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
773
774                 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
775                                 GFP_KERNEL);
776                 if (!ppace) {
777                         cERROR(1, "DACL memory allocation error");
778                         return;
779                 }
780
781                 for (i = 0; i < num_aces; ++i) {
782                         ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
783 #ifdef CONFIG_CIFS_DEBUG2
784                         dump_ace(ppace[i], end_of_acl);
785 #endif
786                         if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
787                                 access_flags_to_mode(ppace[i]->access_req,
788                                                      ppace[i]->type,
789                                                      &fattr->cf_mode,
790                                                      &user_mask);
791                         if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
792                                 access_flags_to_mode(ppace[i]->access_req,
793                                                      ppace[i]->type,
794                                                      &fattr->cf_mode,
795                                                      &group_mask);
796                         if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
797                                 access_flags_to_mode(ppace[i]->access_req,
798                                                      ppace[i]->type,
799                                                      &fattr->cf_mode,
800                                                      &other_mask);
801                         if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
802                                 access_flags_to_mode(ppace[i]->access_req,
803                                                      ppace[i]->type,
804                                                      &fattr->cf_mode,
805                                                      &other_mask);
806
807
808 /*                      memcpy((void *)(&(cifscred->aces[i])),
809                                 (void *)ppace[i],
810                                 sizeof(struct cifs_ace)); */
811
812                         acl_base = (char *)ppace[i];
813                         acl_size = le16_to_cpu(ppace[i]->size);
814                 }
815
816                 kfree(ppace);
817         }
818
819         return;
820 }
821
822
823 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
824                         struct cifs_sid *pgrpsid, __u64 nmode)
825 {
826         u16 size = 0;
827         struct cifs_acl *pnndacl;
828
829         pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
830
831         size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
832                                         pownersid, nmode, S_IRWXU);
833         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
834                                         pgrpsid, nmode, S_IRWXG);
835         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
836                                          &sid_everyone, nmode, S_IRWXO);
837
838         pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
839         pndacl->num_aces = cpu_to_le32(3);
840
841         return 0;
842 }
843
844
845 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
846 {
847         /* BB need to add parm so we can store the SID BB */
848
849         /* validate that we do not go past end of ACL - sid must be at least 8
850            bytes long (assuming no sub-auths - e.g. the null SID */
851         if (end_of_acl < (char *)psid + 8) {
852                 cERROR(1, "ACL too small to parse SID %p", psid);
853                 return -EINVAL;
854         }
855
856         if (psid->num_subauth) {
857 #ifdef CONFIG_CIFS_DEBUG2
858                 int i;
859                 cFYI(1, "SID revision %d num_auth %d",
860                         psid->revision, psid->num_subauth);
861
862                 for (i = 0; i < psid->num_subauth; i++) {
863                         cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
864                                 le32_to_cpu(psid->sub_auth[i]));
865                 }
866
867                 /* BB add length check to make sure that we do not have huge
868                         num auths and therefore go off the end */
869                 cFYI(1, "RID 0x%x",
870                         le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
871 #endif
872         }
873
874         return 0;
875 }
876
877
878 /* Convert CIFS ACL to POSIX form */
879 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
880                 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
881 {
882         int rc = 0;
883         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
884         struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
885         char *end_of_acl = ((char *)pntsd) + acl_len;
886         __u32 dacloffset;
887
888         if (pntsd == NULL)
889                 return -EIO;
890
891         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
892                                 le32_to_cpu(pntsd->osidoffset));
893         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
894                                 le32_to_cpu(pntsd->gsidoffset));
895         dacloffset = le32_to_cpu(pntsd->dacloffset);
896         dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
897         cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
898                  "sacloffset 0x%x dacloffset 0x%x",
899                  pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
900                  le32_to_cpu(pntsd->gsidoffset),
901                  le32_to_cpu(pntsd->sacloffset), dacloffset);
902 /*      cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
903         rc = parse_sid(owner_sid_ptr, end_of_acl);
904         if (rc) {
905                 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
906                 return rc;
907         }
908         rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
909         if (rc) {
910                 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
911                 return rc;
912         }
913
914         rc = parse_sid(group_sid_ptr, end_of_acl);
915         if (rc) {
916                 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
917                 return rc;
918         }
919         rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
920         if (rc) {
921                 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
922                 return rc;
923         }
924
925         if (dacloffset)
926                 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
927                            group_sid_ptr, fattr);
928         else
929                 cFYI(1, "no ACL"); /* BB grant all or default perms? */
930
931 /*      cifscred->uid = owner_sid_ptr->rid;
932         cifscred->gid = group_sid_ptr->rid;
933         memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
934                         sizeof(struct cifs_sid));
935         memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
936                         sizeof(struct cifs_sid)); */
937
938         return rc;
939 }
940
941
942 /* Convert permission bits from mode to equivalent CIFS ACL */
943 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
944                                 struct inode *inode, __u64 nmode)
945 {
946         int rc = 0;
947         __u32 dacloffset;
948         __u32 ndacloffset;
949         __u32 sidsoffset;
950         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
951         struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
952         struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
953
954         if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
955                 return -EIO;
956
957         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
958                                 le32_to_cpu(pntsd->osidoffset));
959         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
960                                 le32_to_cpu(pntsd->gsidoffset));
961
962         dacloffset = le32_to_cpu(pntsd->dacloffset);
963         dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
964
965         ndacloffset = sizeof(struct cifs_ntsd);
966         ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
967         ndacl_ptr->revision = dacl_ptr->revision;
968         ndacl_ptr->size = 0;
969         ndacl_ptr->num_aces = 0;
970
971         rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
972
973         sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
974
975         /* copy security descriptor control portion and owner and group sid */
976         copy_sec_desc(pntsd, pnntsd, sidsoffset);
977
978         return rc;
979 }
980
981 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
982                 __u16 fid, u32 *pacllen)
983 {
984         struct cifs_ntsd *pntsd = NULL;
985         int xid, rc;
986         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
987
988         if (IS_ERR(tlink))
989                 return ERR_CAST(tlink);
990
991         xid = GetXid();
992         rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
993         FreeXid(xid);
994
995         cifs_put_tlink(tlink);
996
997         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
998         if (rc)
999                 return ERR_PTR(rc);
1000         return pntsd;
1001 }
1002
1003 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1004                 const char *path, u32 *pacllen)
1005 {
1006         struct cifs_ntsd *pntsd = NULL;
1007         int oplock = 0;
1008         int xid, rc;
1009         __u16 fid;
1010         struct cifsTconInfo *tcon;
1011         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1012
1013         if (IS_ERR(tlink))
1014                 return ERR_CAST(tlink);
1015
1016         tcon = tlink_tcon(tlink);
1017         xid = GetXid();
1018
1019         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
1020                          &fid, &oplock, NULL, cifs_sb->local_nls,
1021                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1022         if (!rc) {
1023                 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
1024                 CIFSSMBClose(xid, tcon, fid);
1025         }
1026
1027         cifs_put_tlink(tlink);
1028         FreeXid(xid);
1029
1030         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1031         if (rc)
1032                 return ERR_PTR(rc);
1033         return pntsd;
1034 }
1035
1036 /* Retrieve an ACL from the server */
1037 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1038                                       struct inode *inode, const char *path,
1039                                       u32 *pacllen)
1040 {
1041         struct cifs_ntsd *pntsd = NULL;
1042         struct cifsFileInfo *open_file = NULL;
1043
1044         if (inode)
1045                 open_file = find_readable_file(CIFS_I(inode), true);
1046         if (!open_file)
1047                 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1048
1049         pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
1050         cifsFileInfo_put(open_file);
1051         return pntsd;
1052 }
1053
1054 static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
1055                 struct cifs_ntsd *pnntsd, u32 acllen)
1056 {
1057         int xid, rc;
1058         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1059
1060         if (IS_ERR(tlink))
1061                 return PTR_ERR(tlink);
1062
1063         xid = GetXid();
1064         rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
1065         FreeXid(xid);
1066         cifs_put_tlink(tlink);
1067
1068         cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1069         return rc;
1070 }
1071
1072 static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
1073                 struct cifs_ntsd *pnntsd, u32 acllen)
1074 {
1075         int oplock = 0;
1076         int xid, rc;
1077         __u16 fid;
1078         struct cifsTconInfo *tcon;
1079         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1080
1081         if (IS_ERR(tlink))
1082                 return PTR_ERR(tlink);
1083
1084         tcon = tlink_tcon(tlink);
1085         xid = GetXid();
1086
1087         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
1088                          &fid, &oplock, NULL, cifs_sb->local_nls,
1089                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1090         if (rc) {
1091                 cERROR(1, "Unable to open file to set ACL");
1092                 goto out;
1093         }
1094
1095         rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
1096         cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1097
1098         CIFSSMBClose(xid, tcon, fid);
1099 out:
1100         FreeXid(xid);
1101         cifs_put_tlink(tlink);
1102         return rc;
1103 }
1104
1105 /* Set an ACL on the server */
1106 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1107                                 struct inode *inode, const char *path)
1108 {
1109         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1110         struct cifsFileInfo *open_file;
1111         int rc;
1112
1113         cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
1114
1115         open_file = find_readable_file(CIFS_I(inode), true);
1116         if (!open_file)
1117                 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
1118
1119         rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
1120         cifsFileInfo_put(open_file);
1121         return rc;
1122 }
1123
1124 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1125 int
1126 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1127                   struct inode *inode, const char *path, const __u16 *pfid)
1128 {
1129         struct cifs_ntsd *pntsd = NULL;
1130         u32 acllen = 0;
1131         int rc = 0;
1132
1133         cFYI(DBG2, "converting ACL to mode for %s", path);
1134
1135         if (pfid)
1136                 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1137         else
1138                 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
1139
1140         /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1141         if (IS_ERR(pntsd)) {
1142                 rc = PTR_ERR(pntsd);
1143                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1144         } else {
1145                 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1146                 kfree(pntsd);
1147                 if (rc)
1148                         cERROR(1, "parse sec desc failed rc = %d", rc);
1149         }
1150
1151         return rc;
1152 }
1153
1154 /* Convert mode bits to an ACL so we can update the ACL on the server */
1155 int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
1156 {
1157         int rc = 0;
1158         __u32 secdesclen = 0;
1159         struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1160         struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1161
1162         cFYI(DBG2, "set ACL from mode for %s", path);
1163
1164         /* Get the security descriptor */
1165         pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1166
1167         /* Add three ACEs for owner, group, everyone getting rid of
1168            other ACEs as chmod disables ACEs and set the security descriptor */
1169
1170         if (IS_ERR(pntsd)) {
1171                 rc = PTR_ERR(pntsd);
1172                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1173         } else {
1174                 /* allocate memory for the smb header,
1175                    set security descriptor request security descriptor
1176                    parameters, and secuirty descriptor itself */
1177
1178                 secdesclen = secdesclen < DEFSECDESCLEN ?
1179                                         DEFSECDESCLEN : secdesclen;
1180                 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1181                 if (!pnntsd) {
1182                         cERROR(1, "Unable to allocate security descriptor");
1183                         kfree(pntsd);
1184                         return -ENOMEM;
1185                 }
1186
1187                 rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
1188
1189                 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1190
1191                 if (!rc) {
1192                         /* Set the security descriptor */
1193                         rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
1194                         cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1195                 }
1196
1197                 kfree(pnntsd);
1198                 kfree(pntsd);
1199         }
1200
1201         return rc;
1202 }