Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
17 changes: 12 additions & 5 deletions npipe_windows.go
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,12 @@ func dial(address string, timeout uint32) (*PipeConn, error) {
// The address must be of the form \\.\pipe\<name>
//
// 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)
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
Empty file modified npipe_windows_test.go
100755 → 100644
Empty file.
51 changes: 20 additions & 31 deletions sec_attr.go
Original file line number Diff line number Diff line change
@@ -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

}