mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-05 16:47:31 -04:00
Add routine for looking up account names
Signed-off-by: John Starks <jostarks@microsoft.com>
This commit is contained in:
@@ -10,11 +10,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
//sys createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
||||||
//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
|
//sys waitNamedPipe(name string, timeout uint32) (err error) = WaitNamedPipeW
|
||||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
|
||||||
//sys localFree(mem uintptr) = LocalFree
|
type securityAttributes struct {
|
||||||
|
Length uint32
|
||||||
|
SecurityDescriptor *byte
|
||||||
|
InheritHandle uint32
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
cERROR_PIPE_BUSY = syscall.Errno(231)
|
||||||
@@ -127,31 +131,23 @@ type acceptResponse struct {
|
|||||||
type win32PipeListener struct {
|
type win32PipeListener struct {
|
||||||
firstHandle syscall.Handle
|
firstHandle syscall.Handle
|
||||||
path string
|
path string
|
||||||
securityDescriptor string
|
securityDescriptor []byte
|
||||||
acceptCh chan (chan acceptResponse)
|
acceptCh chan (chan acceptResponse)
|
||||||
closeCh chan int
|
closeCh chan int
|
||||||
doneCh chan int
|
doneCh chan int
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeServerPipeHandle(path, securityDescriptor string, first bool) (syscall.Handle, error) {
|
func makeServerPipeHandle(path string, securityDescriptor []byte, first bool) (syscall.Handle, error) {
|
||||||
var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
|
var flags uint32 = cPIPE_ACCESS_DUPLEX | syscall.FILE_FLAG_OVERLAPPED
|
||||||
if first {
|
if first {
|
||||||
flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
|
flags |= cFILE_FLAG_FIRST_PIPE_INSTANCE
|
||||||
}
|
}
|
||||||
var sd uintptr
|
var sa securityAttributes
|
||||||
if securityDescriptor != "" {
|
|
||||||
err := convertStringSecurityDescriptorToSecurityDescriptor(securityDescriptor, 1, &sd, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var sa syscall.SecurityAttributes
|
|
||||||
sa.Length = uint32(unsafe.Sizeof(sa))
|
sa.Length = uint32(unsafe.Sizeof(sa))
|
||||||
sa.SecurityDescriptor = sd
|
if securityDescriptor != nil {
|
||||||
h, err := createNamedPipe(path, flags, cPIPE_REJECT_REMOTE_CLIENTS, cPIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &sa)
|
sa.SecurityDescriptor = &securityDescriptor[0]
|
||||||
if sd != 0 {
|
|
||||||
localFree(sd)
|
|
||||||
}
|
}
|
||||||
|
h, err := createNamedPipe(path, flags, cPIPE_REJECT_REMOTE_CLIENTS, cPIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, &os.PathError{"open", path, err}
|
return 0, &os.PathError{"open", path, err}
|
||||||
}
|
}
|
||||||
@@ -211,8 +207,18 @@ func (l *win32PipeListener) listenerRoutine() {
|
|||||||
close(l.doneCh)
|
close(l.doneCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenPipe(path, securityDescriptor string) (net.Listener, error) {
|
func ListenPipe(path, sddl string) (net.Listener, error) {
|
||||||
h, err := makeServerPipeHandle(path, securityDescriptor, true)
|
var (
|
||||||
|
sd []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if sddl != "" {
|
||||||
|
sd, err = sddlToSecurityDescriptor(sddl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h, err := makeServerPipeHandle(path, sd, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -227,7 +233,7 @@ func ListenPipe(path, securityDescriptor string) (net.Listener, error) {
|
|||||||
l := &win32PipeListener{
|
l := &win32PipeListener{
|
||||||
firstHandle: h,
|
firstHandle: h,
|
||||||
path: path,
|
path: path,
|
||||||
securityDescriptor: securityDescriptor,
|
securityDescriptor: sd,
|
||||||
acceptCh: make(chan (chan acceptResponse)),
|
acceptCh: make(chan (chan acceptResponse)),
|
||||||
closeCh: make(chan int),
|
closeCh: make(chan int),
|
||||||
doneCh: make(chan int),
|
doneCh: make(chan int),
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package winio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
|
||||||
|
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||||
|
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||||
|
//sys localFree(mem uintptr) = LocalFree
|
||||||
|
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||||
|
|
||||||
|
const (
|
||||||
|
cERROR_NONE_MAPPED = syscall.Errno(1332)
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccountLookupError struct {
|
||||||
|
Name string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AccountLookupError) Error() string {
|
||||||
|
if e.Name == "" {
|
||||||
|
return "lookup account: empty account name specified"
|
||||||
|
}
|
||||||
|
var s string
|
||||||
|
switch e.Err {
|
||||||
|
case cERROR_NONE_MAPPED:
|
||||||
|
s = "not found"
|
||||||
|
default:
|
||||||
|
s = e.Err.Error()
|
||||||
|
}
|
||||||
|
return "lookup account " + e.Name + ": " + s
|
||||||
|
}
|
||||||
|
|
||||||
|
type SddlConversionError struct {
|
||||||
|
Sddl string
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SddlConversionError) Error() string {
|
||||||
|
return "convert " + e.Sddl + ": " + e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupSidByName looks up the SID of an account by name
|
||||||
|
func LookupSidByName(name string) (sid string, err error) {
|
||||||
|
if name == "" {
|
||||||
|
return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sidSize, sidNameUse, refDomainSize uint32
|
||||||
|
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
||||||
|
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return "", &AccountLookupError{name, err}
|
||||||
|
}
|
||||||
|
sidBuffer := make([]byte, sidSize)
|
||||||
|
refDomainBuffer := make([]uint16, refDomainSize)
|
||||||
|
err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
|
||||||
|
if err != nil {
|
||||||
|
return "", &AccountLookupError{name, err}
|
||||||
|
}
|
||||||
|
var strBuffer *uint16
|
||||||
|
err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
|
||||||
|
if err != nil {
|
||||||
|
return "", &AccountLookupError{name, err}
|
||||||
|
}
|
||||||
|
sid = syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||||
|
localFree(uintptr(unsafe.Pointer(strBuffer)))
|
||||||
|
return sid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||||
|
var sdBuffer uintptr
|
||||||
|
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &SddlConversionError{sddl, err}
|
||||||
|
}
|
||||||
|
defer localFree(sdBuffer)
|
||||||
|
sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
|
||||||
|
copy(sd, (*[1 << 30]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
|
||||||
|
return sd, nil
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package winio
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestLookupInvalidSid(t *testing.T) {
|
||||||
|
_, err := LookupSidByName(".\\weoifjdsklfj")
|
||||||
|
aerr, ok := err.(*AccountLookupError)
|
||||||
|
if !ok || aerr.Err != cERROR_NONE_MAPPED {
|
||||||
|
t.Fatalf("expected AccountLookupError with ERROR_NONE_MAPPED, got %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLookupValidSid(t *testing.T) {
|
||||||
|
sid, err := LookupSidByName("Everyone")
|
||||||
|
if err != nil || sid != "S-1-1-0" {
|
||||||
|
t.Fatal("expected S-1-1-0, got %s, %s", sid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLookupEmptyNameFails(t *testing.T) {
|
||||||
|
_, err := LookupSidByName(".\\weoifjdsklfj")
|
||||||
|
aerr, ok := err.(*AccountLookupError)
|
||||||
|
if !ok || aerr.Err != cERROR_NONE_MAPPED {
|
||||||
|
t.Fatalf("expected AccountLookupError with ERROR_NONE_MAPPED, got %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package winio
|
package winio
|
||||||
|
|
||||||
//go:generate go run mksyscall_windows.go -output zsyscall.go file.go pipe.go
|
//go:generate go run mksyscall_windows.go -output zsyscall.go file.go pipe.go sd.go
|
||||||
|
|||||||
+46
-4
@@ -19,8 +19,11 @@ var (
|
|||||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||||
procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
|
procWaitNamedPipeW = modkernel32.NewProc("WaitNamedPipeW")
|
||||||
|
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||||
|
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||||
|
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||||
)
|
)
|
||||||
|
|
||||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||||
@@ -84,7 +87,7 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
|
||||||
var _p0 *uint16
|
var _p0 *uint16
|
||||||
_p0, err = syscall.UTF16PtrFromString(name)
|
_p0, err = syscall.UTF16PtrFromString(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,7 +96,7 @@ func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances ui
|
|||||||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *securityAttributes) (handle syscall.Handle, err error) {
|
||||||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
||||||
handle = syscall.Handle(r0)
|
handle = syscall.Handle(r0)
|
||||||
if handle == syscall.InvalidHandle {
|
if handle == syscall.InvalidHandle {
|
||||||
@@ -106,7 +109,7 @@ func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
func createFile(name string, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||||
var _p0 *uint16
|
var _p0 *uint16
|
||||||
_p0, err = syscall.UTF16PtrFromString(name)
|
_p0, err = syscall.UTF16PtrFromString(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -115,7 +118,7 @@ func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAtt
|
|||||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
func _createFile(name *uint16, access uint32, mode uint32, sa *securityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||||
handle = syscall.Handle(r0)
|
handle = syscall.Handle(r0)
|
||||||
if handle == syscall.InvalidHandle {
|
if handle == syscall.InvalidHandle {
|
||||||
@@ -149,6 +152,39 @@ func _waitNamedPipe(name *uint16, timeout uint32) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||||
|
var _p0 *uint16
|
||||||
|
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
|
||||||
|
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = error(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
|
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||||
var _p0 *uint16
|
var _p0 *uint16
|
||||||
_p0, err = syscall.UTF16PtrFromString(str)
|
_p0, err = syscall.UTF16PtrFromString(str)
|
||||||
@@ -174,3 +210,9 @@ func localFree(mem uintptr) {
|
|||||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||||
|
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||||
|
len = uint32(r0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user