github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/dokan/winacl/winacl.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 // Package winacl adds support for various Windows security APIs for Dokan. 6 package winacl 7 8 import ( 9 "reflect" 10 "unsafe" 11 ) 12 13 // CurrentProcessUserSid is a utility to get the 14 // SID of the current user running the process. 15 func CurrentProcessUserSid() (*SID, error) { 16 return currentProcessUserSid() 17 } 18 19 // CurrentProcessPrimaryGroupSid is a utility to get the 20 // SID of the primary group of current user running the process. 21 func CurrentProcessPrimaryGroupSid() (*SID, error) { 22 return currentProcessPrimaryGroupSid() 23 } 24 25 // NewSecurityDescriptorWithBuffer creates a new self-referential 26 // security descriptor in the buffer provided. 27 func NewSecurityDescriptorWithBuffer(bs []byte) *SecurityDescriptor { 28 for i := range bs { 29 bs[i] = 0 30 } 31 var sd = SecurityDescriptor{bytes: bs, 32 curOffset: int(unsafe.Sizeof(selfRelativeSecurityDescriptor{}))} 33 if len(bs) >= sd.curOffset { 34 sd.ptr = (*selfRelativeSecurityDescriptor)(unsafe.Pointer(&bs[0])) 35 sd.ptr.Revision = 1 36 sd.ptr.Control = seSelfRelative | seOwnerDefaulted | seGroupDefaulted 37 } 38 return &sd 39 } 40 41 // SecurityDescriptor is the type for security descriptors. 42 // Note that items have to be set in the following order: 43 // 1) owner, 2) group, 3) sacl, 4) dacl. Some of them may 44 // be omitted. 45 type SecurityDescriptor struct { 46 bytes []byte 47 ptr *selfRelativeSecurityDescriptor 48 curOffset int 49 } 50 51 // Size returns the size of the security descriptor. If the buffer is too 52 // small then it is the size that would be needed to store this 53 // SecurityDescriptor. 54 func (sd *SecurityDescriptor) Size() int { 55 return sd.curOffset 56 } 57 58 // HasOverflowed returns whether this security descriptor is too large for 59 // the provided buffer. 60 func (sd *SecurityDescriptor) HasOverflowed() bool { 61 return sd.curOffset > len(sd.bytes) 62 } 63 64 type selfRelativeSecurityDescriptor struct { 65 Revision, Sbz1 byte 66 Control uint16 67 OwnerOffset, GroupOffset, SaclOffset, DaclOffset int32 68 } 69 70 const ( 71 seOwnerDefaulted = 0x1 72 seGroupDefaulted = 0x2 73 seDaclPresent = 0x4 74 seSelfRelative = 0x8000 75 ) 76 77 // SetOwner sets the owner field of a SecurityDescriptor. 78 func (sd *SecurityDescriptor) SetOwner(sid *SID) { 79 if off := sd.setSid(sid); off != 0 { 80 sd.ptr.OwnerOffset = int32(off) 81 sd.ptr.Control &^= seOwnerDefaulted 82 } 83 } 84 85 // SetGroup sets the owner field of a SecurityDescriptor. 86 func (sd *SecurityDescriptor) SetGroup(sid *SID) { 87 if off := sd.setSid(sid); off != 0 { 88 sd.ptr.GroupOffset = int32(off) 89 sd.ptr.Control &^= seGroupDefaulted 90 } 91 } 92 93 // SetDacl sets a dacl in the security descriptor to the given ACL. 94 func (sd *SecurityDescriptor) SetDacl(acl *ACL) { 95 bs := acl.bytes() 96 off := sd.curOffset 97 sd.curOffset += len(bs) 98 if sd.HasOverflowed() { 99 return 100 } 101 copy(sd.bytes[off:], bs) 102 sd.ptr.Control |= seDaclPresent 103 sd.ptr.DaclOffset = int32(off) 104 } 105 106 func (sd *SecurityDescriptor) setSid(sid *SID) int { 107 size := sidSize(sid) 108 off := sd.curOffset 109 sd.curOffset += size 110 if sd.HasOverflowed() { 111 return 0 112 } 113 copy(sd.bytes[off:], bufToSlice(unsafe.Pointer(sid), size)) 114 return off 115 } 116 117 func sidSize(s *SID) int { 118 return 8 + 4*int(((*sidFixed)(unsafe.Pointer(s))).SubAuthorityCount) 119 } 120 121 type sidFixed struct { 122 Revision, SubAuthorityCount byte 123 IdentifierAuthority [6]byte 124 } 125 126 // bufToSlice returns a byte slice aliasing the pointer and length given as arguments. 127 func bufToSlice(ptr unsafe.Pointer, nbytes int) []byte { 128 if ptr == nil || nbytes == 0 { 129 return nil 130 } 131 return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ 132 Data: uintptr(ptr), 133 Len: nbytes, 134 Cap: nbytes})) 135 }