ReactOS 0.4.16-dev-401-g45b008d
security.c
Go to the documentation of this file.
1/* Copyright (c) Mark Harmstone 2016-17
2 *
3 * This file is part of WinBtrfs.
4 *
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
9 *
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "btrfs_drv.h"
19
20#define SEF_DACL_AUTO_INHERIT 0x01
21#define SEF_SACL_AUTO_INHERIT 0x02
22
23typedef struct {
26 UCHAR auth[6];
27 uint32_t nums[8];
29
30static sid_header sid_BA = { 1, 2, SECURITY_NT_AUTHORITY, {32, 544}}; // BUILTIN\Administrators
31static sid_header sid_SY = { 1, 1, SECURITY_NT_AUTHORITY, {18}}; // NT AUTHORITY\SYSTEM
32static sid_header sid_BU = { 1, 2, SECURITY_NT_AUTHORITY, {32, 545}}; // BUILTIN\Users
33static sid_header sid_AU = { 1, 1, SECURITY_NT_AUTHORITY, {11}}; // NT AUTHORITY\Authenticated Users
34
35typedef struct {
39} dacl;
40
41static dacl def_dacls[] = {
42 { 0, FILE_ALL_ACCESS, &sid_BA },
44 { 0, FILE_ALL_ACCESS, &sid_SY },
49 // FIXME - Mandatory Label\High Mandatory Level:(OI)(NP)(IO)(NW)
50 { 0, 0, NULL }
51};
52
55
56void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t uid) {
57 unsigned int i, np;
58 uint8_t numdashes;
60 ULONG sidsize;
62 uid_map* um;
63
64 if (sidstringlength < 4 ||
65 sidstring[0] != 'S' ||
66 sidstring[1] != '-' ||
67 sidstring[2] != '1' ||
68 sidstring[3] != '-') {
69 ERR("invalid SID\n");
70 return;
71 }
72
73 sidstring = &sidstring[4];
74 sidstringlength -= 4;
75
76 numdashes = 0;
77 for (i = 0; i < sidstringlength; i++) {
78 if (sidstring[i] == '-') {
79 numdashes++;
80 sidstring[i] = 0;
81 }
82 }
83
84 sidsize = 8 + (numdashes * 4);
86 if (!sid) {
87 ERR("out of memory\n");
88 return;
89 }
90
91 sid->revision = 0x01;
92 sid->elements = numdashes;
93
94 np = 0;
95 while (sidstringlength > 0) {
96 val = 0;
97 i = 0;
98 while (sidstring[i] != '-' && i < sidstringlength) {
99 if (sidstring[i] >= '0' && sidstring[i] <= '9') {
100 val *= 10;
101 val += sidstring[i] - '0';
102 } else
103 break;
104
105 i++;
106 }
107
108 i++;
109 TRACE("val = %u, i = %u, ssl = %lu\n", (uint32_t)val, i, sidstringlength);
110
111 if (np == 0) {
112 sid->auth[0] = (uint8_t)((val & 0xff0000000000) >> 40);
113 sid->auth[1] = (uint8_t)((val & 0xff00000000) >> 32);
114 sid->auth[2] = (uint8_t)((val & 0xff000000) >> 24);
115 sid->auth[3] = (uint8_t)((val & 0xff0000) >> 16);
116 sid->auth[4] = (uint8_t)((val & 0xff00) >> 8);
117 sid->auth[5] = val & 0xff;
118 } else {
119 sid->nums[np-1] = (uint32_t)val;
120 }
121
122 np++;
123
124 if (sidstringlength > i) {
125 sidstringlength -= i;
126
127 sidstring = &sidstring[i];
128 } else
129 break;
130 }
131
133 if (!um) {
134 ERR("out of memory\n");
136 return;
137 }
138
139 um->sid = sid;
140 um->uid = uid;
141
143}
144
145void add_group_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t gid) {
146 unsigned int i, np;
147 uint8_t numdashes;
149 ULONG sidsize;
151 gid_map* gm;
152
153 if (sidstringlength < 4 || sidstring[0] != 'S' || sidstring[1] != '-' || sidstring[2] != '1' || sidstring[3] != '-') {
154 ERR("invalid SID\n");
155 return;
156 }
157
158 sidstring = &sidstring[4];
159 sidstringlength -= 4;
160
161 numdashes = 0;
162 for (i = 0; i < sidstringlength; i++) {
163 if (sidstring[i] == '-') {
164 numdashes++;
165 sidstring[i] = 0;
166 }
167 }
168
169 sidsize = 8 + (numdashes * 4);
171 if (!sid) {
172 ERR("out of memory\n");
173 return;
174 }
175
176 sid->revision = 0x01;
177 sid->elements = numdashes;
178
179 np = 0;
180 while (sidstringlength > 0) {
181 val = 0;
182 i = 0;
183 while (i < sidstringlength && sidstring[i] != '-') {
184 if (sidstring[i] >= '0' && sidstring[i] <= '9') {
185 val *= 10;
186 val += sidstring[i] - '0';
187 } else
188 break;
189
190 i++;
191 }
192
193 i++;
194 TRACE("val = %u, i = %u, ssl = %lu\n", (uint32_t)val, i, sidstringlength);
195
196 if (np == 0) {
197 sid->auth[0] = (uint8_t)((val & 0xff0000000000) >> 40);
198 sid->auth[1] = (uint8_t)((val & 0xff00000000) >> 32);
199 sid->auth[2] = (uint8_t)((val & 0xff000000) >> 24);
200 sid->auth[3] = (uint8_t)((val & 0xff0000) >> 16);
201 sid->auth[4] = (uint8_t)((val & 0xff00) >> 8);
202 sid->auth[5] = val & 0xff;
203 } else
204 sid->nums[np-1] = (uint32_t)val;
205
206 np++;
207
208 if (sidstringlength > i) {
209 sidstringlength -= i;
210
211 sidstring = &sidstring[i];
212 } else
213 break;
214 }
215
217 if (!gm) {
218 ERR("out of memory\n");
220 return;
221 }
222
223 gm->sid = sid;
224 gm->gid = gid;
225
227}
228
230 LIST_ENTRY* le;
231 sid_header* sh;
232 UCHAR els;
233
235
236 le = uid_map_list.Flink;
237 while (le != &uid_map_list) {
238 uid_map* um = CONTAINING_RECORD(le, uid_map, listentry);
239
240 if (um->uid == uid) {
242 if (!*sid) {
243 ERR("out of memory\n");
246 }
247
248 RtlCopyMemory(*sid, um->sid, RtlLengthSid(um->sid));
250 return STATUS_SUCCESS;
251 }
252
253 le = le->Flink;
254 }
255
257
258 if (uid == 0) { // root
259 // FIXME - find actual Administrator account, rather than SYSTEM (S-1-5-18)
260 // (of form S-1-5-21-...-500)
261
262 els = 1;
263
264 sh = ExAllocatePoolWithTag(PagedPool, sizeof(sid_header) + ((els - 1) * sizeof(uint32_t)), ALLOC_TAG);
265 if (!sh) {
266 ERR("out of memory\n");
267 *sid = NULL;
269 }
270
271 sh->revision = 1;
272 sh->elements = els;
273
274 sh->auth[0] = 0;
275 sh->auth[1] = 0;
276 sh->auth[2] = 0;
277 sh->auth[3] = 0;
278 sh->auth[4] = 0;
279 sh->auth[5] = 5;
280
281 sh->nums[0] = 18;
282 } else {
283 // fallback to S-1-22-1-X, Samba's SID scheme
285 if (!sh) {
286 ERR("out of memory\n");
287 *sid = NULL;
289 }
290
291 sh->revision = 1;
292 sh->elements = 2;
293
294 sh->auth[0] = 0;
295 sh->auth[1] = 0;
296 sh->auth[2] = 0;
297 sh->auth[3] = 0;
298 sh->auth[4] = 0;
299 sh->auth[5] = 22;
300
301 sh->nums[0] = 1;
302 sh->nums[1] = uid;
303 }
304
305 *sid = sh;
306
307 return STATUS_SUCCESS;
308}
309
311 LIST_ENTRY* le;
312 sid_header* sh = sid;
313
315
316 le = uid_map_list.Flink;
317 while (le != &uid_map_list) {
318 uid_map* um = CONTAINING_RECORD(le, uid_map, listentry);
319
320 if (RtlEqualSid(sid, um->sid)) {
322 return um->uid;
323 }
324
325 le = le->Flink;
326 }
327
329
330 if (RtlEqualSid(sid, &sid_SY))
331 return 0; // root
332
333 // Samba's SID scheme: S-1-22-1-X
334 if (sh->revision == 1 && sh->elements == 2 && sh->auth[0] == 0 && sh->auth[1] == 0 && sh->auth[2] == 0 && sh->auth[3] == 0 &&
335 sh->auth[4] == 0 && sh->auth[5] == 22 && sh->nums[0] == 1)
336 return sh->nums[1];
337
338 return UID_NOBODY;
339}
340
341static void gid_to_sid(uint32_t gid, PSID* sid) {
342 sid_header* sh;
343 UCHAR els;
344
345 // FIXME - do this properly?
346
347 // fallback to S-1-22-2-X, Samba's SID scheme
348 els = 2;
349 sh = ExAllocatePoolWithTag(PagedPool, sizeof(sid_header) + ((els - 1) * sizeof(uint32_t)), ALLOC_TAG);
350 if (!sh) {
351 ERR("out of memory\n");
352 *sid = NULL;
353 return;
354 }
355
356 sh->revision = 1;
357 sh->elements = els;
358
359 sh->auth[0] = 0;
360 sh->auth[1] = 0;
361 sh->auth[2] = 0;
362 sh->auth[3] = 0;
363 sh->auth[4] = 0;
364 sh->auth[5] = 22;
365
366 sh->nums[0] = 2;
367 sh->nums[1] = gid;
368
369 *sid = sh;
370}
371
373 uint16_t size, i;
374 ACL* acl;
376
377 size = sizeof(ACL);
378 i = 0;
379 while (def_dacls[i].sid) {
380 size += sizeof(ACCESS_ALLOWED_ACE);
381 size += 8 + (def_dacls[i].sid->elements * sizeof(uint32_t)) - sizeof(ULONG);
382 i++;
383 }
384
386 if (!acl) {
387 ERR("out of memory\n");
388 return NULL;
389 }
390
392 acl->Sbz1 = 0;
393 acl->AclSize = size;
394 acl->AceCount = i;
395 acl->Sbz2 = 0;
396
397 aaa = (ACCESS_ALLOWED_ACE*)&acl[1];
398 i = 0;
399 while (def_dacls[i].sid) {
402 aaa->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + 8 + (def_dacls[i].sid->elements * sizeof(uint32_t));
403 aaa->Mask = def_dacls[i].mask;
404
405 RtlCopyMemory(&aaa->SidStart, def_dacls[i].sid, 8 + (def_dacls[i].sid->elements * sizeof(uint32_t)));
406
407 aaa = (ACCESS_ALLOWED_ACE*)((uint8_t*)aaa + aaa->Header.AceSize);
408
409 i++;
410 }
411
412 return acl;
413}
414
415static void get_top_level_sd(fcb* fcb) {
418 ULONG buflen;
419 ACL* acl = NULL;
420 PSID usersid = NULL, groupsid = NULL;
421
423
424 if (!NT_SUCCESS(Status)) {
425 ERR("RtlCreateSecurityDescriptor returned %08lx\n", Status);
426 goto end;
427 }
428
429 Status = uid_to_sid(fcb->inode_item.st_uid, &usersid);
430 if (!NT_SUCCESS(Status)) {
431 ERR("uid_to_sid returned %08lx\n", Status);
432 goto end;
433 }
434
435 Status = RtlSetOwnerSecurityDescriptor(&sd, usersid, false);
436
437 if (!NT_SUCCESS(Status)) {
438 ERR("RtlSetOwnerSecurityDescriptor returned %08lx\n", Status);
439 goto end;
440 }
441
442 gid_to_sid(fcb->inode_item.st_gid, &groupsid);
443 if (!groupsid) {
444 ERR("out of memory\n");
445 goto end;
446 }
447
448 Status = RtlSetGroupSecurityDescriptor(&sd, groupsid, false);
449
450 if (!NT_SUCCESS(Status)) {
451 ERR("RtlSetGroupSecurityDescriptor returned %08lx\n", Status);
452 goto end;
453 }
454
455 acl = load_default_acl();
456
457 if (!acl) {
458 ERR("out of memory\n");
459 goto end;
460 }
461
462 Status = RtlSetDaclSecurityDescriptor(&sd, true, acl, false);
463
464 if (!NT_SUCCESS(Status)) {
465 ERR("RtlSetDaclSecurityDescriptor returned %08lx\n", Status);
466 goto end;
467 }
468
469 // FIXME - SACL_SECURITY_INFORMATION
470
471 buflen = 0;
472
473 // get sd size
476 ERR("RtlAbsoluteToSelfRelativeSD 1 returned %08lx\n", Status);
477 goto end;
478 }
479
480 if (buflen == 0 || Status == STATUS_SUCCESS) {
481 TRACE("RtlAbsoluteToSelfRelativeSD said SD is zero-length\n");
482 goto end;
483 }
484
486 if (!fcb->sd) {
487 ERR("out of memory\n");
488 goto end;
489 }
490
492
493 if (!NT_SUCCESS(Status)) {
494 ERR("RtlAbsoluteToSelfRelativeSD 2 returned %08lx\n", Status);
495 ExFreePool(fcb->sd);
496 fcb->sd = NULL;
497 goto end;
498 }
499
500end:
501 if (acl)
502 ExFreePool(acl);
503
504 if (usersid)
505 ExFreePool(usersid);
506
507 if (groupsid)
508 ExFreePool(groupsid);
509}
510
511void fcb_get_sd(fcb* fcb, struct _fcb* parent, bool look_for_xattr, PIRP Irp) {
513 PSID usersid = NULL, groupsid = NULL;
515 ULONG buflen;
518 PACL dacl, sacl;
519 PSID owner, group;
520 ULONG abssdlen = 0, dacllen = 0, sacllen = 0, ownerlen = 0, grouplen = 0;
521 uint8_t* buf;
522
523 if (look_for_xattr && get_xattr(fcb->Vcb, fcb->subvol, fcb->inode, EA_NTACL, EA_NTACL_HASH, (uint8_t**)&fcb->sd, (uint16_t*)&buflen, Irp))
524 return;
525
526 if (!parent) {
528 return;
529 }
530
531 SeCaptureSubjectContext(&subjcont);
532
535 if (!NT_SUCCESS(Status)) {
536 ERR("SeAssignSecurityEx returned %08lx\n", Status);
537 return;
538 }
539
540 Status = RtlSelfRelativeToAbsoluteSD(fcb->sd, NULL, &abssdlen, NULL, &dacllen, NULL, &sacllen, NULL, &ownerlen,
541 NULL, &grouplen);
543 ERR("RtlSelfRelativeToAbsoluteSD returned %08lx\n", Status);
544 return;
545 }
546
547 if (abssdlen + dacllen + sacllen + ownerlen + grouplen == 0) {
548 ERR("RtlSelfRelativeToAbsoluteSD returned zero lengths\n");
549 return;
550 }
551
552 buf = (uint8_t*)ExAllocatePoolWithTag(PagedPool, abssdlen + dacllen + sacllen + ownerlen + grouplen, ALLOC_TAG);
553 if (!buf) {
554 ERR("out of memory\n");
555 return;
556 }
557
558 abssd = (PSECURITY_DESCRIPTOR)buf;
559 dacl = (PACL)(buf + abssdlen);
560 sacl = (PACL)(buf + abssdlen + dacllen);
561 owner = (PSID)(buf + abssdlen + dacllen + sacllen);
562 group = (PSID)(buf + abssdlen + dacllen + sacllen + ownerlen);
563
564 Status = RtlSelfRelativeToAbsoluteSD(fcb->sd, abssd, &abssdlen, dacl, &dacllen, sacl, &sacllen, owner, &ownerlen,
565 group, &grouplen);
567 ERR("RtlSelfRelativeToAbsoluteSD returned %08lx\n", Status);
569 return;
570 }
571
572 Status = uid_to_sid(fcb->inode_item.st_uid, &usersid);
573 if (!NT_SUCCESS(Status)) {
574 ERR("uid_to_sid returned %08lx\n", Status);
576 return;
577 }
578
579 RtlSetOwnerSecurityDescriptor(abssd, usersid, false);
580
581 gid_to_sid(fcb->inode_item.st_gid, &groupsid);
582 if (!groupsid) {
583 ERR("out of memory\n");
584 ExFreePool(usersid);
586 return;
587 }
588
589 RtlSetGroupSecurityDescriptor(abssd, groupsid, false);
590
591 buflen = 0;
592
593 Status = RtlAbsoluteToSelfRelativeSD(abssd, NULL, &buflen);
595 ERR("RtlAbsoluteToSelfRelativeSD returned %08lx\n", Status);
596 ExFreePool(usersid);
597 ExFreePool(groupsid);
599 return;
600 }
601
602 if (buflen == 0) {
603 ERR("RtlAbsoluteToSelfRelativeSD returned a buffer size of 0\n");
604 ExFreePool(usersid);
605 ExFreePool(groupsid);
607 return;
608 }
609
610 newsd = ExAllocatePoolWithTag(PagedPool, buflen, ALLOC_TAG);
611 if (!newsd) {
612 ERR("out of memory\n");
613 ExFreePool(usersid);
614 ExFreePool(groupsid);
616 return;
617 }
618
619 Status = RtlAbsoluteToSelfRelativeSD(abssd, newsd, &buflen);
620 if (!NT_SUCCESS(Status)) {
621 ERR("RtlAbsoluteToSelfRelativeSD returned %08lx\n", Status);
622 ExFreePool(usersid);
623 ExFreePool(groupsid);
625 return;
626 }
627
628 ExFreePool(fcb->sd);
629 fcb->sd = newsd;
630
631 ExFreePool(usersid);
632 ExFreePool(groupsid);
634}
635
638 fcb* fcb = FileObject->FsContext;
639 ccb* ccb = FileObject->FsContext2;
640 file_ref* fileref = ccb ? ccb->fileref : NULL;
641
642 if (fcb->ads) {
643 if (fileref && fileref->parent)
644 fcb = fileref->parent->fcb;
645 else {
646 ERR("could not get parent fcb for stream\n");
648 }
649 }
650
651 // Why (void**)? Is this a bug in mingw?
652 Status = SeQuerySecurityDescriptorInfo(&flags, relsd, buflen, (void**)&fcb->sd);
653
655 TRACE("SeQuerySecurityDescriptorInfo returned %08lx\n", Status);
656 else if (!NT_SUCCESS(Status))
657 ERR("SeQuerySecurityDescriptorInfo returned %08lx\n", Status);
658
659 return Status;
660}
661
668 device_extension* Vcb = DeviceObject->DeviceExtension;
669 ULONG buflen;
670 bool top_level;
672 ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
673
675
676 TRACE("query security\n");
677
678 top_level = is_top_level(Irp);
679
680 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
682 goto end;
683 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
685 goto end;
686 }
687
688 if (!ccb) {
689 ERR("no ccb\n");
691 goto end;
692 }
693
694 if (Irp->RequestorMode == UserMode && !(ccb->access & READ_CONTROL)) {
695 WARN("insufficient permissions\n");
697 goto end;
698 }
699
701
702 Irp->IoStatus.Information = 0;
703
704 if (IrpSp->Parameters.QuerySecurity.SecurityInformation & OWNER_SECURITY_INFORMATION)
705 TRACE("OWNER_SECURITY_INFORMATION\n");
706
707 if (IrpSp->Parameters.QuerySecurity.SecurityInformation & GROUP_SECURITY_INFORMATION)
708 TRACE("GROUP_SECURITY_INFORMATION\n");
709
710 if (IrpSp->Parameters.QuerySecurity.SecurityInformation & DACL_SECURITY_INFORMATION)
711 TRACE("DACL_SECURITY_INFORMATION\n");
712
713 if (IrpSp->Parameters.QuerySecurity.SecurityInformation & SACL_SECURITY_INFORMATION)
714 TRACE("SACL_SECURITY_INFORMATION\n");
715
716 TRACE("length = %lu\n", IrpSp->Parameters.QuerySecurity.Length);
717
719 TRACE("sd = %p\n", sd);
720
721 if (Irp->MdlAddress && !sd) {
722 ERR("MmGetSystemAddressForMdlSafe returned NULL\n");
724 goto end;
725 }
726
727 buflen = IrpSp->Parameters.QuerySecurity.Length;
728
729 Status = get_file_security(IrpSp->FileObject, sd, &buflen, IrpSp->Parameters.QuerySecurity.SecurityInformation);
730
731 if (NT_SUCCESS(Status))
732 Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;
733 else if (Status == STATUS_BUFFER_TOO_SMALL) {
734 Irp->IoStatus.Information = buflen;
736 } else
737 Irp->IoStatus.Information = 0;
738
739end:
740 TRACE("Irp->IoStatus.Information = %Iu\n", Irp->IoStatus.Information);
741
742 Irp->IoStatus.Status = Status;
743
745
746 if (top_level)
748
749 TRACE("returning %08lx\n", Status);
750
752
753 return Status;
754}
755
758 fcb* fcb = FileObject->FsContext;
759 ccb* ccb = FileObject->FsContext2;
760 file_ref* fileref = ccb ? ccb->fileref : NULL;
761 SECURITY_DESCRIPTOR* oldsd;
764
765 TRACE("(%p, %p, %p, %lx)\n", Vcb, FileObject, sd, *flags);
766
767 if (Vcb->readonly)
769
770 if (fcb->ads) {
771 if (fileref && fileref->parent)
772 fcb = fileref->parent->fcb;
773 else {
774 ERR("could not find parent fcb for stream\n");
776 }
777 }
778
779 if (!fcb || !ccb)
781
783
786 goto end;
787 }
788
789 oldsd = fcb->sd;
790
792
793 if (!NT_SUCCESS(Status)) {
794 ERR("SeSetSecurityDescriptorInfo returned %08lx\n", Status);
795 goto end;
796 }
797
798 ExFreePool(oldsd);
799
802
803 fcb->inode_item.transid = Vcb->superblock.generation;
804
807
809
810 fcb->sd_dirty = true;
811 fcb->sd_deleted = false;
812 fcb->inode_item_changed = true;
813
814 fcb->subvol->root_item.ctransid = Vcb->superblock.generation;
815 fcb->subvol->root_item.ctime = now;
816
818
820
821end:
823
824 return Status;
825}
826
833 ccb* ccb = FileObject ? FileObject->FsContext2 : NULL;
834 device_extension* Vcb = DeviceObject->DeviceExtension;
835 ULONG access_req = 0;
836 bool top_level;
837
839
840 TRACE("set security\n");
841
842 top_level = is_top_level(Irp);
843
844 if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
846 goto end;
847 } else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
849 goto end;
850 }
851
852 if (!ccb) {
853 ERR("no ccb\n");
855 goto end;
856 }
857
859
860 Irp->IoStatus.Information = 0;
861
862 if (IrpSp->Parameters.SetSecurity.SecurityInformation & OWNER_SECURITY_INFORMATION) {
863 TRACE("OWNER_SECURITY_INFORMATION\n");
864 access_req |= WRITE_OWNER;
865 }
866
867 if (IrpSp->Parameters.SetSecurity.SecurityInformation & GROUP_SECURITY_INFORMATION) {
868 TRACE("GROUP_SECURITY_INFORMATION\n");
869 access_req |= WRITE_OWNER;
870 }
871
872 if (IrpSp->Parameters.SetSecurity.SecurityInformation & DACL_SECURITY_INFORMATION) {
873 TRACE("DACL_SECURITY_INFORMATION\n");
874 access_req |= WRITE_DAC;
875 }
876
877 if (IrpSp->Parameters.SetSecurity.SecurityInformation & SACL_SECURITY_INFORMATION) {
878 TRACE("SACL_SECURITY_INFORMATION\n");
879 access_req |= ACCESS_SYSTEM_SECURITY;
880 }
881
882 if (Irp->RequestorMode == UserMode && (ccb->access & access_req) != access_req) {
884 WARN("insufficient privileges\n");
885 goto end;
886 }
887
888 Status = set_file_security(DeviceObject->DeviceExtension, FileObject, IrpSp->Parameters.SetSecurity.SecurityDescriptor,
889 &IrpSp->Parameters.SetSecurity.SecurityInformation, Irp);
890
891end:
892 Irp->IoStatus.Status = Status;
893
895
896 TRACE("returning %08lx\n", Status);
897
898 if (top_level)
900
902
903 return Status;
904}
905
906static bool search_for_gid(fcb* fcb, PSID sid) {
907 LIST_ENTRY* le;
908
909 le = gid_map_list.Flink;
910 while (le != &gid_map_list) {
911 gid_map* gm = CONTAINING_RECORD(le, gid_map, listentry);
912
913 if (RtlEqualSid(sid, gm->sid)) {
914 fcb->inode_item.st_gid = gm->gid;
915 return true;
916 }
917
918 le = le->Flink;
919 }
920
921 return false;
922}
923
924void find_gid(struct _fcb* fcb, struct _fcb* parfcb, PSECURITY_SUBJECT_CONTEXT subjcont) {
926 TOKEN_OWNER* to;
928 TOKEN_GROUPS* tg;
929
930 if (parfcb && parfcb->inode_item.st_mode & S_ISGID) {
932 return;
933 }
934
936
937 if (!subjcont || !subjcont->PrimaryToken || IsListEmpty(&gid_map_list)) {
939 return;
940 }
941
942 Status = SeQueryInformationToken(subjcont->PrimaryToken, TokenOwner, (void**)&to);
943 if (!NT_SUCCESS(Status))
944 ERR("SeQueryInformationToken returned %08lx\n", Status);
945 else {
946 if (search_for_gid(fcb, to->Owner)) {
948 ExFreePool(to);
949 return;
950 }
951
952 ExFreePool(to);
953 }
954
956 if (!NT_SUCCESS(Status))
957 ERR("SeQueryInformationToken returned %08lx\n", Status);
958 else {
959 if (search_for_gid(fcb, tpg->PrimaryGroup)) {
961 ExFreePool(tpg);
962 return;
963 }
964
965 ExFreePool(tpg);
966 }
967
968 Status = SeQueryInformationToken(subjcont->PrimaryToken, TokenGroups, (void**)&tg);
969 if (!NT_SUCCESS(Status))
970 ERR("SeQueryInformationToken returned %08lx\n", Status);
971 else {
972 ULONG i;
973
974 for (i = 0; i < tg->GroupCount; i++) {
975 if (search_for_gid(fcb, tg->Groups[i].Sid)) {
977 ExFreePool(tg);
978 return;
979 }
980 }
981
982 ExFreePool(tg);
983 }
984
986}
987
990 PSID owner;
991 BOOLEAN defaulted;
992
993 Status = SeAssignSecurityEx(parfileref ? parfileref->fcb->sd : NULL, as->SecurityDescriptor, (void**)&fcb->sd, NULL, fcb->type == BTRFS_TYPE_DIRECTORY,
995
996 if (!NT_SUCCESS(Status)) {
997 ERR("SeAssignSecurityEx returned %08lx\n", Status);
998 return Status;
999 }
1000
1001 Status = RtlGetOwnerSecurityDescriptor(fcb->sd, &owner, &defaulted);
1002 if (!NT_SUCCESS(Status)) {
1003 ERR("RtlGetOwnerSecurityDescriptor returned %08lx\n", Status);
1005 } else {
1006 fcb->inode_item.st_uid = sid_to_uid(owner);
1007 }
1008
1009 find_gid(fcb, parfileref ? parfileref->fcb : NULL, &as->SubjectSecurityContext);
1010
1011 return STATUS_SUCCESS;
1012}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
unsigned short int uint16_t
Definition: acefiex.h:54
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define VCB_TYPE_VOLUME
Definition: btrfs_drv.h:689
#define EA_NTACL_HASH
Definition: btrfs_drv.h:94
#define _Dispatch_type_(a)
Definition: btrfs_drv.h:204
#define UID_NOBODY
Definition: btrfs_drv.h:90
#define EA_NTACL
Definition: btrfs_drv.h:93
static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME *out)
Definition: btrfs_drv.h:989
#define VCB_TYPE_FS
Definition: btrfs_drv.h:687
#define ALLOC_TAG
Definition: btrfs_drv.h:87
static __inline void * map_user_buffer(PIRP Irp, ULONG priority)
Definition: btrfs_drv.h:977
static __inline bool is_subvol_readonly(root *r, PIRP Irp)
Definition: btrfs_drv.h:1033
FT_UInt sid
Definition: cffcmap.c:139
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
void mark_fcb_dirty(_In_ fcb *fcb)
Definition: btrfs.c:1695
r parent
Definition: btrfs.c:3010
bool is_top_level(_In_ PIRP Irp)
Definition: btrfs.c:278
void queue_notification_fcb(_In_ file_ref *fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream)
Definition: btrfs.c:1667
static bool search_for_gid(fcb *fcb, PSID sid)
Definition: security.c:906
void add_user_mapping(WCHAR *sidstring, ULONG sidstringlength, uint32_t uid)
Definition: security.c:56
void add_group_mapping(WCHAR *sidstring, ULONG sidstringlength, uint32_t gid)
Definition: security.c:145
uint32_t sid_to_uid(PSID sid)
Definition: security.c:310
NTSTATUS uid_to_sid(uint32_t uid, PSID *sid)
Definition: security.c:229
void fcb_get_sd(fcb *fcb, struct _fcb *parent, bool look_for_xattr, PIRP Irp)
Definition: security.c:511
#define SEF_DACL_AUTO_INHERIT
Definition: security.c:20
static sid_header sid_SY
Definition: security.c:31
static void get_top_level_sd(fcb *fcb)
Definition: security.c:415
static sid_header sid_BA
Definition: security.c:30
void find_gid(struct _fcb *fcb, struct _fcb *parfcb, PSECURITY_SUBJECT_CONTEXT subjcont)
Definition: security.c:924
ERESOURCE mapping_lock
Definition: btrfs.c:103
static NTSTATUS get_file_security(PFILE_OBJECT FileObject, SECURITY_DESCRIPTOR *relsd, ULONG *buflen, SECURITY_INFORMATION flags)
Definition: security.c:636
static ACL * load_default_acl()
Definition: security.c:372
LIST_ENTRY uid_map_list
Definition: btrfs.c:68
#define SEF_SACL_AUTO_INHERIT
Definition: security.c:21
static void gid_to_sid(uint32_t gid, PSID *sid)
Definition: security.c:341
static sid_header sid_AU
Definition: security.c:33
LIST_ENTRY gid_map_list
Definition: security.c:53
static sid_header sid_BU
Definition: security.c:32
static dacl def_dacls[]
Definition: security.c:41
NTSTATUS fcb_get_new_sd(fcb *fcb, file_ref *parfileref, ACCESS_STATE *as)
Definition: security.c:988
static NTSTATUS set_file_security(device_extension *Vcb, PFILE_OBJECT FileObject, SECURITY_DESCRIPTOR *sd, PSECURITY_INFORMATION flags, PIRP Irp)
Definition: security.c:756
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define PagedPool
Definition: env_spec_w32.h:308
time_t now
Definition: finger.c:65
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
GLuint GLuint end
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLboolean GLuint group
Definition: glext.h:11120
GLuint GLfloat * val
Definition: glext.h:7180
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSYSAPI NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR, PSID, BOOLEAN)
NTSYSAPI NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, PDWORD, PACL, PDWORD, PACL, PDWORD, PSID, PDWORD, PSID, PDWORD)
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
__u16 time
Definition: mkdosfs.c:8
@ NormalPagePriority
Definition: imports.h:54
static const WCHAR sd[]
Definition: suminfo.c:286
struct _SID * PSID
Definition: eventlog.c:35
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
struct _SECURITY_DESCRIPTOR * PSECURITY_DESCRIPTOR
Definition: security.c:98
struct _ACL ACL
struct _ACL * PACL
Definition: security.c:105
struct _ACCESS_ALLOWED_ACE ACCESS_ALLOWED_ACE
DWORD * PSECURITY_INFORMATION
Definition: ms-dtyp.idl:311
BYTE uint8_t
Definition: msvideo1.c:66
#define UserMode
Definition: asm.h:39
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
NTSYSAPI BOOLEAN NTAPI RtlEqualSid(_In_ PSID Sid1, _In_ PSID Sid2)
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define _Function_class_(n)
Definition: no_sal2.h:398
#define uint32_t
Definition: nsiface.idl:61
#define uint8_t
Definition: nsiface.idl:59
#define WRITE_DAC
Definition: nt_native.h:59
#define FILE_GENERIC_EXECUTE
Definition: nt_native.h:668
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define ACCESS_SYSTEM_SECURITY
Definition: nt_native.h:77
#define DELETE
Definition: nt_native.h:57
#define READ_CONTROL
Definition: nt_native.h:58
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define WRITE_OWNER
Definition: nt_native.h:60
#define FILE_GENERIC_READ
Definition: nt_native.h:653
#define FILE_GENERIC_WRITE
Definition: nt_native.h:660
NTSYSAPI NTSTATUS NTAPI RtlSetGroupSecurityDescriptor(IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN PSID Group, IN BOOLEAN GroupDefaulted)
Definition: sd.c:410
NTSYSAPI NTSTATUS NTAPI RtlGetOwnerSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PSID *Owner, OUT PBOOLEAN OwnerDefaulted)
Definition: sd.c:257
NTSYSAPI NTSTATUS NTAPI RtlAbsoluteToSelfRelativeSD(IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor, IN PULONG BufferLength)
Definition: sd.c:626
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
PGENERIC_MAPPING NTAPI IoGetFileObjectGenericMapping(VOID)
Definition: file.c:3267
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define Vcb
Definition: cdprocs.h:1415
#define S_ISGID
Definition: propsheet.h:69
short sh
Definition: format.c:272
#define BTRFS_TYPE_DIRECTORY
Definition: shellext.h:86
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define TRACE(s)
Definition: solgame.cpp:4
uint32_t st_mode
Definition: btrfs.h:295
uint32_t st_uid
Definition: btrfs.h:293
uint64_t sequence
Definition: btrfs.h:299
BTRFS_TIME st_ctime
Definition: btrfs.h:302
uint64_t transid
Definition: btrfs.h:288
uint32_t st_gid
Definition: btrfs.h:294
ACE_HEADER Header
Definition: ms-dtyp.idl:216
ACCESS_MASK Mask
Definition: ms-dtyp.idl:217
PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: setypes.h:235
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
Definition: setypes.h:234
USHORT AceSize
Definition: ms-dtyp.idl:212
UCHAR AceFlags
Definition: ms-dtyp.idl:211
UCHAR AceType
Definition: ms-dtyp.idl:210
USHORT Sbz2
Definition: ms-dtyp.idl:298
UCHAR Sbz1
Definition: ms-dtyp.idl:295
USHORT AceCount
Definition: ms-dtyp.idl:297
USHORT AclSize
Definition: ms-dtyp.idl:296
UCHAR AclRevision
Definition: ms-dtyp.idl:294
struct _IO_STACK_LOCATION::@3983::@4002 SetSecurity
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct _IO_STACK_LOCATION::@3983::@4001 QuerySecurity
union _IO_STACK_LOCATION::@1584 Parameters
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PACCESS_TOKEN PrimaryToken
Definition: setypes.h:220
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:1018
$ULONG GroupCount
Definition: setypes.h:1014
PSID Owner
Definition: setypes.h:1028
bool user_set_change_time
Definition: btrfs_drv.h:390
ACCESS_MASK access
Definition: btrfs_drv.h:382
file_ref * fileref
Definition: btrfs_drv.h:383
bool ads
Definition: btrfs_drv.h:330
bool sd_dirty
Definition: btrfs_drv.h:321
uint64_t inode
Definition: btrfs_drv.h:289
SECURITY_DESCRIPTOR * sd
Definition: btrfs_drv.h:293
INODE_ITEM inode_item
Definition: btrfs_drv.h:292
uint8_t type
Definition: btrfs_drv.h:291
struct _device_extension * Vcb
Definition: btrfs_drv.h:287
struct _root * subvol
Definition: btrfs_drv.h:288
bool sd_deleted
Definition: btrfs_drv.h:321
bool inode_item_changed
Definition: btrfs_drv.h:306
FSRTL_ADVANCED_FCB_HEADER Header
Definition: btrfs_drv.h:283
struct _file_ref * parent
Definition: btrfs_drv.h:352
fcb * fcb
Definition: btrfs_drv.h:342
Definition: security.c:35
UCHAR flags
Definition: security.c:36
sid_header * sid
Definition: security.c:38
ACCESS_MASK mask
Definition: security.c:37
uint32_t gid
Definition: btrfs_drv.h:911
PSID sid
Definition: btrfs_drv.h:910
LIST_ENTRY listentry
Definition: btrfs_drv.h:909
UCHAR revision
Definition: security.c:24
UCHAR elements
Definition: security.c:25
LIST_ENTRY listentry
Definition: btrfs_drv.h:903
PSID sid
Definition: btrfs_drv.h:904
uint32_t uid
Definition: btrfs_drv.h:905
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
NTSTATUS NTAPI SeQueryInformationToken(_In_ PACCESS_TOKEN AccessToken, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Outptr_result_buffer_(_Inexpressible_(token-dependent)) PVOID *TokenInformation)
Queries information details about the given token to the call. The difference between NtQueryInformat...
Definition: tokencls.c:95
#define __stdcall
Definition: typedefs.h:25
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FILE_ACTION_MODIFIED
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define FILE_NOTIFY_CHANGE_SECURITY
#define IRP_MJ_QUERY_SECURITY
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MJ_SET_SECURITY
NTKERNELAPI NTSTATUS NTAPI SeAssignSecurityEx(_In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, _In_opt_ PSECURITY_DESCRIPTOR ExplicitDescriptor, _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, _In_opt_ GUID *ObjectType, _In_ BOOLEAN IsDirectoryObject, _In_ ULONG AutoInheritFlags, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ PGENERIC_MAPPING GenericMapping, _In_ POOL_TYPE PoolType)
NTKERNELAPI NTSTATUS NTAPI SeSetSecurityDescriptorInfo(_In_opt_ PVOID Object, _In_ PSECURITY_INFORMATION SecurityInformation, _In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, _In_ POOL_TYPE PoolType, _In_ PGENERIC_MAPPING GenericMapping)
NTKERNELAPI NTSTATUS NTAPI SeQuerySecurityDescriptorInfo(_In_ PSECURITY_INFORMATION SecurityInformation, _Out_writes_bytes_(*Length) PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PULONG Length, _Inout_ PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
#define CONTAINER_INHERIT_ACE
Definition: setypes.h:747
#define INHERIT_ONLY_ACE
Definition: setypes.h:749
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
#define ACCESS_ALLOWED_ACE_TYPE
Definition: setypes.h:717
#define OWNER_SECURITY_INFORMATION
Definition: setypes.h:123
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:554
#define OBJECT_INHERIT_ACE
Definition: setypes.h:746
@ TokenGroups
Definition: setypes.h:967
@ TokenPrimaryGroup
Definition: setypes.h:970
@ TokenOwner
Definition: setypes.h:969
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124
#define ACL_REVISION
Definition: setypes.h:39
#define SACL_SECURITY_INFORMATION
Definition: setypes.h:126
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180