github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/osext/winsvc/svc/security.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package svc 6 7 import ( 8 "chai2010.gopkg/osext/winsvc/winapi" 9 "syscall" 10 "unsafe" 11 ) 12 13 // TODO(brainman): move some of that code to syscall/security.go 14 15 // getInfo retrieves a specified type of information about an access token. 16 func getInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) { 17 b := make([]byte, initSize) 18 var n uint32 19 e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) 20 if e != nil { 21 if e != syscall.ERROR_INSUFFICIENT_BUFFER { 22 return nil, e 23 } 24 // make receive buffers of requested size and try again 25 b = make([]byte, n) 26 e = syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) 27 if e != nil { 28 return nil, e 29 } 30 } 31 return unsafe.Pointer(&b[0]), nil 32 } 33 34 // getTokenUser retrieves access token t user account information. 35 func getTokenGroups(t syscall.Token) (*winapi.Tokengroups, error) { 36 i, e := getInfo(t, syscall.TokenGroups, 50) 37 if e != nil { 38 return nil, e 39 } 40 return (*winapi.Tokengroups)(i), nil 41 } 42 43 func allocSid(subAuth0 uint32) (*syscall.SID, error) { 44 var sid *syscall.SID 45 err := winapi.AllocateAndInitializeSid(&winapi.SECURITY_NT_AUTHORITY, 46 1, subAuth0, 0, 0, 0, 0, 0, 0, 0, &sid) 47 if err != nil { 48 return nil, err 49 } 50 return sid, nil 51 } 52 53 // IsAnInteractiveSession determines if calling process is running interactively. 54 // It queries the process token for membership in the Interactive group. 55 // http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s 56 func IsAnInteractiveSession() (bool, error) { 57 interSid, err := allocSid(winapi.SECURITY_INTERACTIVE_RID) 58 if err != nil { 59 return false, err 60 } 61 defer winapi.FreeSid(interSid) 62 63 serviceSid, err := allocSid(winapi.SECURITY_SERVICE_RID) 64 if err != nil { 65 return false, err 66 } 67 defer winapi.FreeSid(serviceSid) 68 69 t, err := syscall.OpenCurrentProcessToken() 70 if err != nil { 71 return false, err 72 } 73 defer t.Close() 74 75 gs, err := getTokenGroups(t) 76 if err != nil { 77 return false, err 78 } 79 p := unsafe.Pointer(&gs.Groups[0]) 80 groups := (*[256]syscall.SIDAndAttributes)(p)[:gs.GroupCount] 81 for _, g := range groups { 82 if winapi.EqualSid(g.Sid, interSid) { 83 return true, nil 84 } 85 if winapi.EqualSid(g.Sid, serviceSid) { 86 return false, nil 87 } 88 } 89 return false, nil 90 } 91 92 // IsAnIinteractiveSession is a misspelled version of IsAnInteractiveSession. 93 // Do not use. It is kept here so we do not break existing code. 94 func IsAnIinteractiveSession() (bool, error) { 95 return IsAnInteractiveSession() 96 }