diff --git a/example_windows_test.go b/example_windows_test.go index 14595ae..f5d36c5 100644 --- a/example_windows_test.go +++ b/example_windows_test.go @@ -26,7 +26,7 @@ func ExampleDial() { // Use Listen to start a server, and accept connections with Accept(). func ExampleListen() { - ln, err := npipe.Listen(`\\.\pipe\mypipe`) + ln, err := npipe.Listen(`\\.\pipe\mypipe`, npipe.AllowEveryone) if err != nil { // handle error } diff --git a/npipe_windows.go b/npipe_windows.go old mode 100755 new mode 100644 index 8bae0c3..ec825ed --- a/npipe_windows.go +++ b/npipe_windows.go @@ -253,8 +253,12 @@ func dial(address string, timeout uint32) (*PipeConn, error) { // The address must be of the form \\.\pipe\ // // Listen will return a PipeError for an incorrectly formatted pipe name. -func Listen(address string) (*PipeListener, error) { - handle, err := createPipe(address, true) +func Listen(address string, SDDL ...string) (*PipeListener, error) { + var sddl string + if len(SDDL) > 0 { + sddl = SDDL[0] + } + handle, err := createPipe(address, true, sddl) if err == error_invalid_name { return nil, badAddr(address) } @@ -295,7 +299,7 @@ func (l *PipeListener) AcceptPipe() (*PipeConn, error) { handle := l.handle if handle == 0 { var err error - handle, err = createPipe(string(l.addr), false) + handle, err = createPipe(string(l.addr), false, ``) if err != nil { return nil, err } @@ -463,7 +467,7 @@ func (a PipeAddr) String() string { // with the same arguments, since subsequent calls to create pipe need // to use the same arguments as the first one. If first is set, fail // if the pipe already exists. -func createPipe(address string, first bool) (syscall.Handle, error) { +func createPipe(address string, first bool, SDDL string) (syscall.Handle, error) { n, err := syscall.UTF16PtrFromString(address) if err != nil { return 0, err @@ -473,10 +477,13 @@ func createPipe(address string, first bool) (syscall.Handle, error) { mode |= file_flag_first_pipe_instance } - sa, err := initSecurityAttributes() + sa, err := initSecurityAttributes(SDDL) if err != nil { return 0, err } + if 0 != sa.SecurityDescriptor { + defer syscall.LocalFree((syscall.Handle)(sa.SecurityDescriptor)) + } return createNamedPipe(n, mode, diff --git a/npipe_windows_test.go b/npipe_windows_test.go old mode 100755 new mode 100644 diff --git a/sec_attr.go b/sec_attr.go index a2179fa..4e10aec 100644 --- a/sec_attr.go +++ b/sec_attr.go @@ -1,46 +1,35 @@ package npipe import ( - "os" "syscall" "unsafe" ) -const SECURITY_DESCRIPTOR_REVISION = 1 +const SDDL_REVISION_1 = 1 +const AllowEveryone = `D:(A;;FA;;;WD)` +const AllowAnonymous = `D:(A;;FA;;;AN)` var ( - advapi32 = syscall.NewLazyDLL("advapi32.dll") - procInitializeSecurityDescriptor = advapi32.NewProc("InitializeSecurityDescriptor") - procSetSecurityDescriptorDacl = advapi32.NewProc("SetSecurityDescriptorDacl") + advapi32 = syscall.NewLazyDLL("advapi32.dll") + procConvertStringSecurityDescriptorToSecurityDescriptor = advapi32.NewProc(`ConvertStringSecurityDescriptorToSecurityDescriptorW`) ) -func initSecurityAttributes() (*syscall.SecurityAttributes, error) { - - // create security descriptor - sd := make([]byte, 4096) - if res, _, err := procInitializeSecurityDescriptor.Call( - uintptr(unsafe.Pointer(&sd[0])), - SECURITY_DESCRIPTOR_REVISION); int(res) == 0 { - - return nil, os.NewSyscallError("InitializeSecurityDescriptor", err) - } - - // configure security descriptor - present := 1 - defaulted := 0 - if res, _, err := procSetSecurityDescriptorDacl.Call( - uintptr(unsafe.Pointer(&sd[0])), - uintptr(present), - uintptr(unsafe.Pointer(nil)), // acl - uintptr(defaulted)); int(res) == 0 { - - return nil, os.NewSyscallError("SetSecurityDescriptorDacl", err) - } - +func initSecurityAttributes(SDDL string) (*syscall.SecurityAttributes, error) { var sa syscall.SecurityAttributes sa.Length = uint32(unsafe.Sizeof(sa)) - sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) - + if `` != SDDL { + u, err := syscall.UTF16PtrFromString(SDDL) + if nil != err { + return nil, err + } + r0, _, err := procConvertStringSecurityDescriptorToSecurityDescriptor.Call( + uintptr(unsafe.Pointer(u)), + SDDL_REVISION_1, + uintptr(unsafe.Pointer(&sa.SecurityDescriptor)), + uintptr(0)) + if 0 == r0 { + return nil, err + } + } return &sa, nil - }