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  }