cifs: Add idmap key and related data structures and functions (try #17 repost)
[deliverable/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
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 static const struct cred *root_cred;
58
59 /*
60 * Run idmap cache shrinker.
61 */
62 static int
63 cifs_idmap_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
64 {
65 /* Use a pruning scheme in a subsequent patch instead */
66 cifs_destroy_idmaptrees();
67 return 0;
68 }
69
70 static struct shrinker cifs_shrinker = {
71 .shrink = cifs_idmap_shrinker,
72 .seeks = DEFAULT_SEEKS,
73 };
74
75 static int
76 cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
77 {
78 char *payload;
79
80 payload = kmalloc(datalen, GFP_KERNEL);
81 if (!payload)
82 return -ENOMEM;
83
84 memcpy(payload, data, datalen);
85 key->payload.data = payload;
86 return 0;
87 }
88
89 static inline void
90 cifs_idmap_key_destroy(struct key *key)
91 {
92 kfree(key->payload.data);
93 }
94
95 static
96 struct key_type cifs_idmap_key_type = {
97 .name = "cifs.cifs_idmap",
98 .instantiate = cifs_idmap_key_instantiate,
99 .destroy = cifs_idmap_key_destroy,
100 .describe = user_describe,
101 .match = user_match,
102 };
103
104 int
105 init_cifs_idmap(void)
106 {
107 struct cred *cred;
108 struct key *keyring;
109 int ret;
110
111 cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
112
113 /* create an override credential set with a special thread keyring in
114 * which requests are cached
115 *
116 * this is used to prevent malicious redirections from being installed
117 * with add_key().
118 */
119 cred = prepare_kernel_cred(NULL);
120 if (!cred)
121 return -ENOMEM;
122
123 keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
124 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
125 KEY_USR_VIEW | KEY_USR_READ,
126 KEY_ALLOC_NOT_IN_QUOTA);
127 if (IS_ERR(keyring)) {
128 ret = PTR_ERR(keyring);
129 goto failed_put_cred;
130 }
131
132 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
133 if (ret < 0)
134 goto failed_put_key;
135
136 ret = register_key_type(&cifs_idmap_key_type);
137 if (ret < 0)
138 goto failed_put_key;
139
140 /* instruct request_key() to use this special keyring as a cache for
141 * the results it looks up */
142 cred->thread_keyring = keyring;
143 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
144 root_cred = cred;
145
146 spin_lock_init(&siduidlock);
147 uidtree = RB_ROOT;
148 spin_lock_init(&sidgidlock);
149 gidtree = RB_ROOT;
150
151 register_shrinker(&cifs_shrinker);
152
153 cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
154 return 0;
155
156 failed_put_key:
157 key_put(keyring);
158 failed_put_cred:
159 put_cred(cred);
160 return ret;
161 }
162
163 void
164 exit_cifs_idmap(void)
165 {
166 key_revoke(root_cred->thread_keyring);
167 unregister_key_type(&cifs_idmap_key_type);
168 put_cred(root_cred);
169 unregister_shrinker(&cifs_shrinker);
170 cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
171 }
172
173 void
174 cifs_destroy_idmaptrees(void)
175 {
176 struct rb_root *root;
177 struct rb_node *node;
178
179 root = &uidtree;
180 spin_lock(&siduidlock);
181 while ((node = rb_first(root)))
182 rb_erase(node, root);
183 spin_unlock(&siduidlock);
184
185 root = &gidtree;
186 spin_lock(&sidgidlock);
187 while ((node = rb_first(root)))
188 rb_erase(node, root);
189 spin_unlock(&sidgidlock);
190 }
191
192 int match_sid(struct cifs_sid *ctsid)
193 {
194 int i, j;
195 int num_subauth, num_sat, num_saw;
196 struct cifs_sid *cwsid;
197
198 if (!ctsid)
199 return -1;
200
201 for (i = 0; i < NUM_WK_SIDS; ++i) {
202 cwsid = &(wksidarr[i].cifssid);
203
204 /* compare the revision */
205 if (ctsid->revision != cwsid->revision)
206 continue;
207
208 /* compare all of the six auth values */
209 for (j = 0; j < 6; ++j) {
210 if (ctsid->authority[j] != cwsid->authority[j])
211 break;
212 }
213 if (j < 6)
214 continue; /* all of the auth values did not match */
215
216 /* compare all of the subauth values if any */
217 num_sat = ctsid->num_subauth;
218 num_saw = cwsid->num_subauth;
219 num_subauth = num_sat < num_saw ? num_sat : num_saw;
220 if (num_subauth) {
221 for (j = 0; j < num_subauth; ++j) {
222 if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
223 break;
224 }
225 if (j < num_subauth)
226 continue; /* all sub_auth values do not match */
227 }
228
229 cFYI(1, "matching sid: %s\n", wksidarr[i].sidname);
230 return 0; /* sids compare/match */
231 }
232
233 cFYI(1, "No matching sid");
234 return -1;
235 }
236
237 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
238 the same returns 1, if they do not match returns 0 */
239 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
240 {
241 int i;
242 int num_subauth, num_sat, num_saw;
243
244 if ((!ctsid) || (!cwsid))
245 return 0;
246
247 /* compare the revision */
248 if (ctsid->revision != cwsid->revision)
249 return 0;
250
251 /* compare all of the six auth values */
252 for (i = 0; i < 6; ++i) {
253 if (ctsid->authority[i] != cwsid->authority[i])
254 return 0;
255 }
256
257 /* compare all of the subauth values if any */
258 num_sat = ctsid->num_subauth;
259 num_saw = cwsid->num_subauth;
260 num_subauth = num_sat < num_saw ? num_sat : num_saw;
261 if (num_subauth) {
262 for (i = 0; i < num_subauth; ++i) {
263 if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
264 return 0;
265 }
266 }
267
268 return 1; /* sids compare/match */
269 }
270
271
272 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
273 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
274 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
275 {
276 int i;
277
278 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
279 struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
280
281 /* copy security descriptor control portion */
282 pnntsd->revision = pntsd->revision;
283 pnntsd->type = pntsd->type;
284 pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
285 pnntsd->sacloffset = 0;
286 pnntsd->osidoffset = cpu_to_le32(sidsoffset);
287 pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
288
289 /* copy owner sid */
290 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
291 le32_to_cpu(pntsd->osidoffset));
292 nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
293
294 nowner_sid_ptr->revision = owner_sid_ptr->revision;
295 nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
296 for (i = 0; i < 6; i++)
297 nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
298 for (i = 0; i < 5; i++)
299 nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
300
301 /* copy group sid */
302 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
303 le32_to_cpu(pntsd->gsidoffset));
304 ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
305 sizeof(struct cifs_sid));
306
307 ngroup_sid_ptr->revision = group_sid_ptr->revision;
308 ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
309 for (i = 0; i < 6; i++)
310 ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
311 for (i = 0; i < 5; i++)
312 ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
313
314 return;
315 }
316
317
318 /*
319 change posix mode to reflect permissions
320 pmode is the existing mode (we only want to overwrite part of this
321 bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
322 */
323 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
324 umode_t *pbits_to_set)
325 {
326 __u32 flags = le32_to_cpu(ace_flags);
327 /* the order of ACEs is important. The canonical order is to begin with
328 DENY entries followed by ALLOW, otherwise an allow entry could be
329 encountered first, making the subsequent deny entry like "dead code"
330 which would be superflous since Windows stops when a match is made
331 for the operation you are trying to perform for your user */
332
333 /* For deny ACEs we change the mask so that subsequent allow access
334 control entries do not turn on the bits we are denying */
335 if (type == ACCESS_DENIED) {
336 if (flags & GENERIC_ALL)
337 *pbits_to_set &= ~S_IRWXUGO;
338
339 if ((flags & GENERIC_WRITE) ||
340 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
341 *pbits_to_set &= ~S_IWUGO;
342 if ((flags & GENERIC_READ) ||
343 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
344 *pbits_to_set &= ~S_IRUGO;
345 if ((flags & GENERIC_EXECUTE) ||
346 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
347 *pbits_to_set &= ~S_IXUGO;
348 return;
349 } else if (type != ACCESS_ALLOWED) {
350 cERROR(1, "unknown access control type %d", type);
351 return;
352 }
353 /* else ACCESS_ALLOWED type */
354
355 if (flags & GENERIC_ALL) {
356 *pmode |= (S_IRWXUGO & (*pbits_to_set));
357 cFYI(DBG2, "all perms");
358 return;
359 }
360 if ((flags & GENERIC_WRITE) ||
361 ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
362 *pmode |= (S_IWUGO & (*pbits_to_set));
363 if ((flags & GENERIC_READ) ||
364 ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
365 *pmode |= (S_IRUGO & (*pbits_to_set));
366 if ((flags & GENERIC_EXECUTE) ||
367 ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
368 *pmode |= (S_IXUGO & (*pbits_to_set));
369
370 cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
371 return;
372 }
373
374 /*
375 Generate access flags to reflect permissions mode is the existing mode.
376 This function is called for every ACE in the DACL whose SID matches
377 with either owner or group or everyone.
378 */
379
380 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
381 __u32 *pace_flags)
382 {
383 /* reset access mask */
384 *pace_flags = 0x0;
385
386 /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
387 mode &= bits_to_use;
388
389 /* check for R/W/X UGO since we do not know whose flags
390 is this but we have cleared all the bits sans RWX for
391 either user or group or other as per bits_to_use */
392 if (mode & S_IRUGO)
393 *pace_flags |= SET_FILE_READ_RIGHTS;
394 if (mode & S_IWUGO)
395 *pace_flags |= SET_FILE_WRITE_RIGHTS;
396 if (mode & S_IXUGO)
397 *pace_flags |= SET_FILE_EXEC_RIGHTS;
398
399 cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
400 return;
401 }
402
403 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
404 const struct cifs_sid *psid, __u64 nmode, umode_t bits)
405 {
406 int i;
407 __u16 size = 0;
408 __u32 access_req = 0;
409
410 pntace->type = ACCESS_ALLOWED;
411 pntace->flags = 0x0;
412 mode_to_access_flags(nmode, bits, &access_req);
413 if (!access_req)
414 access_req = SET_MINIMUM_RIGHTS;
415 pntace->access_req = cpu_to_le32(access_req);
416
417 pntace->sid.revision = psid->revision;
418 pntace->sid.num_subauth = psid->num_subauth;
419 for (i = 0; i < 6; i++)
420 pntace->sid.authority[i] = psid->authority[i];
421 for (i = 0; i < psid->num_subauth; i++)
422 pntace->sid.sub_auth[i] = psid->sub_auth[i];
423
424 size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
425 pntace->size = cpu_to_le16(size);
426
427 return size;
428 }
429
430
431 #ifdef CONFIG_CIFS_DEBUG2
432 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
433 {
434 int num_subauth;
435
436 /* validate that we do not go past end of acl */
437
438 if (le16_to_cpu(pace->size) < 16) {
439 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
440 return;
441 }
442
443 if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
444 cERROR(1, "ACL too small to parse ACE");
445 return;
446 }
447
448 num_subauth = pace->sid.num_subauth;
449 if (num_subauth) {
450 int i;
451 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
452 pace->sid.revision, pace->sid.num_subauth, pace->type,
453 pace->flags, le16_to_cpu(pace->size));
454 for (i = 0; i < num_subauth; ++i) {
455 cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
456 le32_to_cpu(pace->sid.sub_auth[i]));
457 }
458
459 /* BB add length check to make sure that we do not have huge
460 num auths and therefore go off the end */
461 }
462
463 return;
464 }
465 #endif
466
467
468 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
469 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
470 struct cifs_fattr *fattr)
471 {
472 int i;
473 int num_aces = 0;
474 int acl_size;
475 char *acl_base;
476 struct cifs_ace **ppace;
477
478 /* BB need to add parm so we can store the SID BB */
479
480 if (!pdacl) {
481 /* no DACL in the security descriptor, set
482 all the permissions for user/group/other */
483 fattr->cf_mode |= S_IRWXUGO;
484 return;
485 }
486
487 /* validate that we do not go past end of acl */
488 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
489 cERROR(1, "ACL too small to parse DACL");
490 return;
491 }
492
493 cFYI(DBG2, "DACL revision %d size %d num aces %d",
494 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
495 le32_to_cpu(pdacl->num_aces));
496
497 /* reset rwx permissions for user/group/other.
498 Also, if num_aces is 0 i.e. DACL has no ACEs,
499 user/group/other have no permissions */
500 fattr->cf_mode &= ~(S_IRWXUGO);
501
502 acl_base = (char *)pdacl;
503 acl_size = sizeof(struct cifs_acl);
504
505 num_aces = le32_to_cpu(pdacl->num_aces);
506 if (num_aces > 0) {
507 umode_t user_mask = S_IRWXU;
508 umode_t group_mask = S_IRWXG;
509 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
510
511 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
512 GFP_KERNEL);
513 if (!ppace) {
514 cERROR(1, "DACL memory allocation error");
515 return;
516 }
517
518 for (i = 0; i < num_aces; ++i) {
519 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
520 #ifdef CONFIG_CIFS_DEBUG2
521 dump_ace(ppace[i], end_of_acl);
522 #endif
523 if (compare_sids(&(ppace[i]->sid), pownersid))
524 access_flags_to_mode(ppace[i]->access_req,
525 ppace[i]->type,
526 &fattr->cf_mode,
527 &user_mask);
528 if (compare_sids(&(ppace[i]->sid), pgrpsid))
529 access_flags_to_mode(ppace[i]->access_req,
530 ppace[i]->type,
531 &fattr->cf_mode,
532 &group_mask);
533 if (compare_sids(&(ppace[i]->sid), &sid_everyone))
534 access_flags_to_mode(ppace[i]->access_req,
535 ppace[i]->type,
536 &fattr->cf_mode,
537 &other_mask);
538 if (compare_sids(&(ppace[i]->sid), &sid_authusers))
539 access_flags_to_mode(ppace[i]->access_req,
540 ppace[i]->type,
541 &fattr->cf_mode,
542 &other_mask);
543
544
545 /* memcpy((void *)(&(cifscred->aces[i])),
546 (void *)ppace[i],
547 sizeof(struct cifs_ace)); */
548
549 acl_base = (char *)ppace[i];
550 acl_size = le16_to_cpu(ppace[i]->size);
551 }
552
553 kfree(ppace);
554 }
555
556 return;
557 }
558
559
560 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
561 struct cifs_sid *pgrpsid, __u64 nmode)
562 {
563 u16 size = 0;
564 struct cifs_acl *pnndacl;
565
566 pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
567
568 size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
569 pownersid, nmode, S_IRWXU);
570 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
571 pgrpsid, nmode, S_IRWXG);
572 size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
573 &sid_everyone, nmode, S_IRWXO);
574
575 pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
576 pndacl->num_aces = cpu_to_le32(3);
577
578 return 0;
579 }
580
581
582 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
583 {
584 /* BB need to add parm so we can store the SID BB */
585
586 /* validate that we do not go past end of ACL - sid must be at least 8
587 bytes long (assuming no sub-auths - e.g. the null SID */
588 if (end_of_acl < (char *)psid + 8) {
589 cERROR(1, "ACL too small to parse SID %p", psid);
590 return -EINVAL;
591 }
592
593 if (psid->num_subauth) {
594 #ifdef CONFIG_CIFS_DEBUG2
595 int i;
596 cFYI(1, "SID revision %d num_auth %d",
597 psid->revision, psid->num_subauth);
598
599 for (i = 0; i < psid->num_subauth; i++) {
600 cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
601 le32_to_cpu(psid->sub_auth[i]));
602 }
603
604 /* BB add length check to make sure that we do not have huge
605 num auths and therefore go off the end */
606 cFYI(1, "RID 0x%x",
607 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
608 #endif
609 }
610
611 return 0;
612 }
613
614
615 /* Convert CIFS ACL to POSIX form */
616 static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
617 struct cifs_fattr *fattr)
618 {
619 int rc;
620 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
621 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
622 char *end_of_acl = ((char *)pntsd) + acl_len;
623 __u32 dacloffset;
624
625 if (pntsd == NULL)
626 return -EIO;
627
628 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
629 le32_to_cpu(pntsd->osidoffset));
630 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
631 le32_to_cpu(pntsd->gsidoffset));
632 dacloffset = le32_to_cpu(pntsd->dacloffset);
633 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
634 cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
635 "sacloffset 0x%x dacloffset 0x%x",
636 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
637 le32_to_cpu(pntsd->gsidoffset),
638 le32_to_cpu(pntsd->sacloffset), dacloffset);
639 /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
640 rc = parse_sid(owner_sid_ptr, end_of_acl);
641 if (rc)
642 return rc;
643
644 rc = parse_sid(group_sid_ptr, end_of_acl);
645 if (rc)
646 return rc;
647
648 if (dacloffset)
649 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
650 group_sid_ptr, fattr);
651 else
652 cFYI(1, "no ACL"); /* BB grant all or default perms? */
653
654 /* cifscred->uid = owner_sid_ptr->rid;
655 cifscred->gid = group_sid_ptr->rid;
656 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
657 sizeof(struct cifs_sid));
658 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
659 sizeof(struct cifs_sid)); */
660
661 return 0;
662 }
663
664
665 /* Convert permission bits from mode to equivalent CIFS ACL */
666 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
667 struct inode *inode, __u64 nmode)
668 {
669 int rc = 0;
670 __u32 dacloffset;
671 __u32 ndacloffset;
672 __u32 sidsoffset;
673 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
674 struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */
675 struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
676
677 if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
678 return -EIO;
679
680 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
681 le32_to_cpu(pntsd->osidoffset));
682 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
683 le32_to_cpu(pntsd->gsidoffset));
684
685 dacloffset = le32_to_cpu(pntsd->dacloffset);
686 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
687
688 ndacloffset = sizeof(struct cifs_ntsd);
689 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
690 ndacl_ptr->revision = dacl_ptr->revision;
691 ndacl_ptr->size = 0;
692 ndacl_ptr->num_aces = 0;
693
694 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode);
695
696 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
697
698 /* copy security descriptor control portion and owner and group sid */
699 copy_sec_desc(pntsd, pnntsd, sidsoffset);
700
701 return rc;
702 }
703
704 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
705 __u16 fid, u32 *pacllen)
706 {
707 struct cifs_ntsd *pntsd = NULL;
708 int xid, rc;
709 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
710
711 if (IS_ERR(tlink))
712 return ERR_CAST(tlink);
713
714 xid = GetXid();
715 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
716 FreeXid(xid);
717
718 cifs_put_tlink(tlink);
719
720 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
721 if (rc)
722 return ERR_PTR(rc);
723 return pntsd;
724 }
725
726 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
727 const char *path, u32 *pacllen)
728 {
729 struct cifs_ntsd *pntsd = NULL;
730 int oplock = 0;
731 int xid, rc;
732 __u16 fid;
733 struct cifsTconInfo *tcon;
734 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
735
736 if (IS_ERR(tlink))
737 return ERR_CAST(tlink);
738
739 tcon = tlink_tcon(tlink);
740 xid = GetXid();
741
742 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
743 &fid, &oplock, NULL, cifs_sb->local_nls,
744 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
745 if (!rc) {
746 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
747 CIFSSMBClose(xid, tcon, fid);
748 }
749
750 cifs_put_tlink(tlink);
751 FreeXid(xid);
752
753 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
754 if (rc)
755 return ERR_PTR(rc);
756 return pntsd;
757 }
758
759 /* Retrieve an ACL from the server */
760 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
761 struct inode *inode, const char *path,
762 u32 *pacllen)
763 {
764 struct cifs_ntsd *pntsd = NULL;
765 struct cifsFileInfo *open_file = NULL;
766
767 if (inode)
768 open_file = find_readable_file(CIFS_I(inode), true);
769 if (!open_file)
770 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
771
772 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
773 cifsFileInfo_put(open_file);
774 return pntsd;
775 }
776
777 static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
778 struct cifs_ntsd *pnntsd, u32 acllen)
779 {
780 int xid, rc;
781 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
782
783 if (IS_ERR(tlink))
784 return PTR_ERR(tlink);
785
786 xid = GetXid();
787 rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
788 FreeXid(xid);
789 cifs_put_tlink(tlink);
790
791 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
792 return rc;
793 }
794
795 static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
796 struct cifs_ntsd *pnntsd, u32 acllen)
797 {
798 int oplock = 0;
799 int xid, rc;
800 __u16 fid;
801 struct cifsTconInfo *tcon;
802 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
803
804 if (IS_ERR(tlink))
805 return PTR_ERR(tlink);
806
807 tcon = tlink_tcon(tlink);
808 xid = GetXid();
809
810 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
811 &fid, &oplock, NULL, cifs_sb->local_nls,
812 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
813 if (rc) {
814 cERROR(1, "Unable to open file to set ACL");
815 goto out;
816 }
817
818 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
819 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
820
821 CIFSSMBClose(xid, tcon, fid);
822 out:
823 FreeXid(xid);
824 cifs_put_tlink(tlink);
825 return rc;
826 }
827
828 /* Set an ACL on the server */
829 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
830 struct inode *inode, const char *path)
831 {
832 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
833 struct cifsFileInfo *open_file;
834 int rc;
835
836 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
837
838 open_file = find_readable_file(CIFS_I(inode), true);
839 if (!open_file)
840 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
841
842 rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
843 cifsFileInfo_put(open_file);
844 return rc;
845 }
846
847 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
848 int
849 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
850 struct inode *inode, const char *path, const __u16 *pfid)
851 {
852 struct cifs_ntsd *pntsd = NULL;
853 u32 acllen = 0;
854 int rc = 0;
855
856 cFYI(DBG2, "converting ACL to mode for %s", path);
857
858 if (pfid)
859 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
860 else
861 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
862
863 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
864 if (IS_ERR(pntsd)) {
865 rc = PTR_ERR(pntsd);
866 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
867 } else {
868 rc = parse_sec_desc(pntsd, acllen, fattr);
869 kfree(pntsd);
870 if (rc)
871 cERROR(1, "parse sec desc failed rc = %d", rc);
872 }
873
874 return rc;
875 }
876
877 /* Convert mode bits to an ACL so we can update the ACL on the server */
878 int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
879 {
880 int rc = 0;
881 __u32 secdesclen = 0;
882 struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
883 struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
884
885 cFYI(DBG2, "set ACL from mode for %s", path);
886
887 /* Get the security descriptor */
888 pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
889
890 /* Add three ACEs for owner, group, everyone getting rid of
891 other ACEs as chmod disables ACEs and set the security descriptor */
892
893 if (IS_ERR(pntsd)) {
894 rc = PTR_ERR(pntsd);
895 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
896 } else {
897 /* allocate memory for the smb header,
898 set security descriptor request security descriptor
899 parameters, and secuirty descriptor itself */
900
901 secdesclen = secdesclen < DEFSECDESCLEN ?
902 DEFSECDESCLEN : secdesclen;
903 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
904 if (!pnntsd) {
905 cERROR(1, "Unable to allocate security descriptor");
906 kfree(pntsd);
907 return -ENOMEM;
908 }
909
910 rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
911
912 cFYI(DBG2, "build_sec_desc rc: %d", rc);
913
914 if (!rc) {
915 /* Set the security descriptor */
916 rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
917 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
918 }
919
920 kfree(pnntsd);
921 kfree(pntsd);
922 }
923
924 return rc;
925 }
This page took 0.05397 seconds and 5 git commands to generate.